I have a value that looks like this
lazy var authHeaders: [String: String] = {
if shouldTokenBeRefreshed() {
let semaphore = DispatchSemaphore(value: 0)
refreshTokens {
semaphore.signal()
}
semaphore.wait()
}
return ["Authorization": "Bearer \(module.client.credential.oauthToken)"]
}()
The idea is, when requesting my auth headers
, if my token has expired I will refresh it and then return the new value instead.
func refreshTokens(completion: @escaping () -> Void) {
guard let token = keychain.get("refresh_token") else { return }
module.renewAccessToken(
withRefreshToken: token,
success: { [weak self] credential, response, parameters in
guard let self = self else { return }
self.storeTokens([
"access_token": credential.oauthToken,
"refresh_token": credential.oauthRefreshToken
])
completion()
},
failure: { error in
print(error.description)
})
}
As this is an async
operation, I have tried to pause the flow using a Semaphore
so I can cause it to continue once the completion block is triggered.
The call is not resolving however and I am unsure why.
This is not how you should use DispatchSemaphore
.
Please do not force async code to be synchronous.
You will need to refactor your code to better handle the async nature of what you are trying to achieve.
A completion handler is the simpler, more efficient way to go. If you are trying to avoid this for some reason, take a look at PromiseKit or something other async helper library.
An alternative suggestion would be rather than updating your tokens pre flight, update them on a 401 and then replay your original, updated request.