Samuel T. Chou
Samuel T. Chou

Reputation: 561

Firebase user ID token: when does it change? And how to listen to the updates/refreshes of it?

TL;DR

After/at when does FirebaseUser.getIdToken() return a different value? (When does expiration/update happen?) And how do I monitor/listen to its updates?

The Setup

Our Android project needs to setup with a Firebase Project, where provides a bunch of APIs.

Most of APIs require user authentication token. We use Firebase User's ID token as header, like all of common projects:

Firebase.auth.currentUser?.getIdToken(false).addOnSuccessListener {
    it.token?.let { token -> callAPI(token) }
}

fun callAPI(token: String) {
    val header = "Bearer $token"
    // call out API
}

To manage functions, we split them into several parts, including User Repo and API modules. Due to this setup, I'd like to lazy-update the token (using an Interceptor etc.) -- whenever the token updates, updates Interceptor's header set.

However, I got myself lost in the documentation...

What is ID token?

Firebase provides too many kinds of token, which confuses me a lot. To narrow it down, I'd like to know which token means, or is equal to FirebaseUser.getIdToken().

The most possible answer lays in Firebase Auth User Documentation:

  1. "Current user's access token", which is refreshed when (1) token expires (when...?) (2) user changes password (3) user re-authenticate
  2. The "refresh token" which appears in the same paragraph.
  3. "Firebase ID token": It might be the one most obvious same to getIdToken. However the doc only pointed out that these tokens are "signed JWTs" and does not indicate when will it expire/update.

Which of above is equal to FirebaseUser.getIdToken()?

When does ID Token expire/update?

As described above, if "access token" is equal to ID Token, does that mean:

  1. ID token will expire (at when?) and it is a very common situation?
  2. When user changes password, ID token will also update?
  3. When user re-authenticate (including login, logout, register?), ID token will also update?

Also another most-resulted one doc in my search is Firebase Admin's Manage User Sessions.

The doc also tells when does refresh token expire, such as user deleted/disable/email or password changed. However I don't think those situation apply to ID token's expiration...?

How do I monitor/listen to refresh/updates?

All of above questions can actually be ignored. What I care most is -- how do I listen (detects) when the token is updated?

As far as I know, only function I found is

firebaseUser.getIdToken(false)

Which returns a Task, and doesn't really works much like a lifetime-listener.

I found another one function:

Firebase.auth.addIdTokenListener(FirebaseAuth.IdTokenListener { firebaseAuth ->
    // do something with firebaseAuth...?
})

However I don't know how to use it. Should I call firebaseUser.getIdToken inside?

I'm looking forward something like

firebaseUser.addOnIDTokenRefreshListener

but I can't find it. Is there anything I missed?


That's all of my question. Any information/clarification/experience will help me a lot. Thanks.

Upvotes: 2

Views: 5246

Answers (2)

Samuel T. Chou
Samuel T. Chou

Reputation: 561

Time has passed and I finally collected enough info.

Let's talk about Firebase ID Token:

  • When does it expire/update?
  • How do I monitor/listen to its refresh/updates?
  • What is it?

When does Firebase ID Token expire/update?

From

Firebase ID tokens are short lived, and will be refreshed when:

  • after 1 hour
  • user signs in
  • user signs out
  • user changes password
  • user requires a force-refresh (by executing getIDToken(true))
  • other firebase event, like "user changes"

The procedure seems controlled by Firebase system. The time listed above might not cover all the cases.

How do I monitor/listen to refresh/updates?

Due to the propose of Firebase ID token, you are not suggested to "listen to its changes automatically".

It's suggested to get token dynamically, by calling user.getIdToken().

However, if you really want to monitor it, you may use FirebaseAuth.addIdTokenListener. Note that user (as well as IdToken ) might not always exist in this listener:

Firebase.auth.addIdTokenListener(FirebaseAuth.IdTokenListener { auth ->
    Log.v("AUTH", "token Listener: triggers when user is ${auth.currentUser?.uid}")
    auth.currentUser?.run {
        getIdToken(false).addOnSuccessListener {
            Log.v("AUTH", "token Listener: current token is ${it.token}")
        }.addOnFailureListener {
            Log.w("AUTH", "token Listener: failed getting token.", it)
        }
    }
})

Also note that calling getIdToken(true) would ALWAYS refresh ID token.

Bonus: What is ID Token?

Firstly one have to know that, ID token, refresh and access token is NOT invented by Firebase. It's from the Network framework and protocol -- ID token is from Open ID Connect, and others from OAuth 2.0.

I'm not an expert in Network, so I'll just brief explain it from my understanding:

  • ID Token: always encoded as JWT (JSON Web Token). Provides the identity of user. However it is not very safe as it might be stolen/copied, thus not suggested to be used in API.
  • Access Token: no strict format (can also be JWT), but is limited, dynamic token generated (by server) from client request. Have many ways to keep safety, thus suggested to be used in API.
  • (and a Refresh Token is sent from server, used by client/server, to refresh the Access Token.)

(I recommend a comparison article of these 2 tokens, very clear and helpful.)

However, there're differences in Firebase. In all articles I found, they all indicate that: when you need an access token in Firebase, you should call FirebaseUser.getIdToken(). And it's dynamic, with refreshing mechanism, and you can refresh it from client.

Considered the definition above, I feel like that in Firebase, Firebase (Auth) ID Token behaves more like Access Token defined in OAuth 2.0, not ID Token defined in Open ID Connect.

That's all I got so far. Hope it helps the future googlers.

Upvotes: 3

Frank van Puffelen
Frank van Puffelen

Reputation: 599686

ID tokens in Firebase are short-lived tokens that are valid for an hour after they are minted. About 5 minutes before the current ID token expires, the Firebase SDKs request a new token from the serve and start using that. At this point they also notify any ID token listeners that were registered by calling addIdTokenListener.

When the Firebase SDKs themselves need the ID token to send it with a call to the server, they call getIdToken() and pass the value along. Since most server-side calls are fairly short, the current ID token will be valid long enough for that call to complete, and is also what I'd recommend for most use-cases others may have for getting and passing the ID token. Monitoring the ID token or forcing a refresh are (or at least should be) relatively uncommon in comparison.

Upvotes: 2

Related Questions