1

The flow for my application:

Login into Firebase through iOS. Retrieve the firebase token and store in the keychain -

FIRAuth.auth()?.currentUser?.getTokenWithCompletion({ (token, err) in
  //store token in keychain
})

This token is sent in the header to my node server to authenticate requests -

firebase.auth().verifyIdToken(firebaseAccessToken).then(function(decodedToken) {
  //allow access to api
}

The token then expires after an hour. My question is how should I handle this?

  • Store the time the token was retrieved on the client and force a refresh if needed
  • Refresh the token for every API call
  • Use the token to authenticate, then create another token server side with a longer expiration time and store this as the auth token

Or is there another option here?

jeh
  • 2,373
  • 4
  • 23
  • 38

2 Answers2

4

Storing the token on the keychain manually is effectively fighting – and incorrectly reimplementing – the behavior provided by the Firebase SDK. You should not do that in the first place.

Then, the second option is the cleanest: call getTokenWithCompletion every time before calling your backend service. It's a cheap call, as it will only refresh the token if it has expired.

vzsg
  • 2,831
  • 17
  • 20
1

In my iOS app using Firebase 5, I handle the 60 minute expiration of the Firebase authentication token by implementing an IDTokenDidChangeListener(). The Listener fires on token expiration, and getTokenID() then returns a refreshed token:

import FirebaseAuth

class UserAuthorizer {
    var tokenChangeListener: IDTokenDidChangeListenerHandle?
...
...
...
    // Create a listener for token expiration so the token can be renewed.
    self.tokenChangeListener = Auth.auth().addIDTokenDidChangeListener() { (auth, user) in
        if let user = user {
                // Get the token, renewing it if the 60 minute expiration
                //  has occurred.
                user.getIDToken { idToken, error in
                    if let error = error {
                        // Handle error
                        print("getIDToken error: \(error)")
                        return;
                    }

                    print("getIDToken token: \(String(describing: idToken))")

                    // Reauthorize Firebase with the new token: idToken
                    …
                    …
                    …
                }
            }
        }
...
...
...
    //
    // Sign-Out Firebase.                                                       
    //
    func signOut() {
        …
        …
        …       
        // Remove the token ID listenter.
        guard let tokenListener = self.tokenChangeListener else { return }
        Auth.auth().removeStateDidChangeListener(tokenListener)
        self.tokenChangeListener = nil
    }