I feel like there is an obvious solution to this that is on the tip of my brain, but I can't seem to figure it out. I am using the FirebaseAuth library, so I can't edit it (or I don't want to go down that path). The function getIDTokenForcingRefresh()
uses dispatch_async
. This would be a lot easier if it used the async/await functionality from Swift 5.5, but I have to rely on solutions for dispatch_async
. I need to grab the output to run a Firebase function request using the token. The following obviously doesn't work because the function will return before getIDTokenForcingRefresh()
is finished. I don't care if the main thread is blocked because the user can't proceed in the app until this is done.
var userToken: String {
print("FIREBASE: Getting User Token")
var token = ""
Auth.auth().currentUser?.getIDTokenForcingRefresh(true) { idToken, error in
if let error = error {
print("FIREBASE: There was an error getting the user token")
return
}
print("FIREBASE: Got user token: \(idToken ?? "NONE")")
token = idToken ?? ""
}
print("FIREBASE: Token: \(token)")
return token
}
Even with a completion handler method like getIDTokenForcingRefresh
you can take advantage of async/await
by wrapping the asynchronous function with completion handler in a Continuation
. The error handling is for free
func getUserToken() async throws -> String {
print("FIREBASE: Getting User Token")
return withCheckedThrowingContinuation { continuation in
Auth.auth().currentUser?.getIDTokenForcingRefresh(true) { idToken, error in
if let error {
print("FIREBASE: There was an error getting the user token: \(error.localizedDescription)")
continuation.resume(throwing: error)
} else {
print("FIREBASE: Got user token: \(idToken ?? "NONE")")
continuation.resume(returning: idToken!)
}
}
}
}
And use it
Task {
do {
let token = try await getUserToken()
} catch {
print(error)
}
}
Doesn't Firebase
support async/await
meanwhile?