dylanjha
dylanjha

Reputation: 2513

Error: Firebase ID token has expired

On my server I'm seeing these errors when using firebase admin sdk .verifyIdToken()

Firebase ID token has expired. Get a fresh token from your client app and try again

Firebase ID token has "kid" claim which does not correspond to a known public key. Most likely the ID token is expired, so get a fresh token from your client app and try again. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.

On the client side I'm doing this before every request between browser <> server:

firebase.auth().currentUser.getIdToken()

It's my understanding from reading the docs that this function will get a valid, non-expired token because the SDK in the background will refresh itself as-needed. Optionally, I can pass in true to this function to force a refresh.

Why does this getIdToken() function seem to be sending expired tokens to my backend?

It seems like to resolve this my options are:

  1. Pass in true to force refresh every time I call getIdToken(). This is needlessly expensive because it will add the overhead of a whole round-trip network request from the browser <> firebase before the request from browser <> my server
  2. call getIdToken() the way I am now - decode the token manually on the client side, check the expiration, if it is expired then call getIdToken(true) again to force a refresh and send that newly refreshed token to my server

Is number 2 the recommended/expected way to deal with this? It seems like something is wrong here...

Upvotes: 61

Views: 40674

Answers (9)

Petro
Petro

Reputation: 3642

I have found the answer:

Steps to Resolve

Go to Google Cloud Console → IAM & Admin → Service Accounts https://console.cloud.google.com/iam-admin/

Find the service account used by /opt/yourapp/auth.json

Click Edit or Permissions, then add the “Firebase Admin SDK Administrator Service Agent” or “Firebase Authentication Admin” role.

enter image description hereenter image description here

After that, the code: await admin.auth().createSessionCookie(token, { expiresIn });

Once that’s in place, you’ll no longer see insufficient permission errors, and the session cookie creation should work as expected

Upvotes: 0

Afraz
Afraz

Reputation: 33

const user = firebase.auth().currentUser

const { token } = await user.getIdTokenResult(true)

Try this. Using this method won't expire the token

Upvotes: 0

isuru
isuru

Reputation: 3565

Error: Firebase ID token has expired

You will get this error when your device time is wrong. Check your device clock time as well.

Upvotes: 10

Francois MUGOROZI
Francois MUGOROZI

Reputation: 299

I faced the same problem before and after some try and error, I found out that it was being caused by time sync.

I set my computer time and time zone to automatic and fixed the issue. Also, remember to add "true" in getIdToken(true)

Upvotes: 4

Rahul Kumar
Rahul Kumar

Reputation: 49

If you are using token on your backend, then you can do the following,

1.Check token on backend

2.If token has expired, send 401 unauthorized.

3.On the client, check if status code is 401 unautorized, if so call getIdToken and save new token

Upvotes: 4

Martin De Simone
Martin De Simone

Reputation: 2148

Another possible solution above the mentioned, is that your browser (Or system) date is wrong. Is it almost always related to the date.

Upvotes: 11

Andranik
Andranik

Reputation: 2849

Did you notice that there is an async way of getting the token?

            mAuth.getCurrentUser().getIdToken(false).addOnSuccessListener(new OnSuccessListener<GetTokenResult>() {
            @Override
            public void onSuccess(GetTokenResult getTokenResult) {
                long time = System.currentTimeMillis() - starttime;

                Log.d("testt", "time " + time + ", token " + getTokenResult.getToken());
            }
        });

Not sure, but I guess that it does internal checking and if token is not valid any more(for example there was a refreshed token broadcast for current user and it didn't reached to the user for some reason, network issue for example), it requests new one and returns that.

P.S. I am doing a research on this topic as well and will update if will find out anything new.

Upvotes: 0

Stephane Paquet
Stephane Paquet

Reputation: 2343

Try using something more like this:

Auth.auth().currentUser.getIDTokenForcingRefresh(true) { (token, err) in

/* your code to manage error and success */

}

Upvotes: 0

bojeil
bojeil

Reputation: 30788

The token expires after typically an hour. getIdToken will refresh the cached token if it is expired. Make sure you always call that on the client when you need to send the token to your server. If you cache the token and always send it to your backend, it will be expired at some point.

Also just in case, ensure your server clock is synchronized. It is unlikely but your clock could be out of sync for some reason.

Upvotes: 38

Related Questions