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.