2

I am using Firebase authentication to authenticate users. Whenever, the user is logged in, I get the user's ID token with user.getIdToken(true) and set it on the local storage. With that token in the authorization header, I am requesting my back-end API.

On the back-end side, I am using Firebase admin SDK to authenticate the request and the user with the client-side ID token passed in the request authorization header.

This works for a while. But after some time I get error:

ExpiredIdTokenError: Token expired, 1620908095 < 1620915515

I saw that Firebase refreshes the ID token on its own. But I don't think that's the case. I have looked through the developer tools network tab, and there's also an observer method to check whenever the token has changed => onIdTokenChanged(), but the token is never refreshed.

I couldn't find any information on the Firebase docs either, and I was hoping if you could help me:

  • How can I generate a token without expiration limit to last until signed out or at least for some more time (1 week maybe)?
  • If I cannot the set the expiry limit of the token, what steps should I take so that I can send a valid unexpired token when I am request data from my back-end? Do I have to call user.getIdToken(true) every-time and get a fresh token before I request from my back-end API?
Msw Tm
  • 461
  • 2
  • 14

1 Answers1

2

The idTokenChanged() observer is a bit misleading. It will fire when the token is refreshed, but the token is only refreshed automatically when you also use other Firebase products (like its database or file storage). In other cases, as you said you should call user.getIdToken(), which will refresh an expired token for you if necessary, everytime you call your API. You don't need to pass true into this method unless you want to have a completely fresh token everytime (which you most likely don't need).

To my knowledge you cannot control the expiration of tokens generated with the client SDK, for that you would need to generate your own tokens on the server.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
puelo
  • 5,464
  • 2
  • 34
  • 62
  • *firebaser here* The ID token of the signed in user *is* automatically refreshed, and ID token changed listeners are called when that happens. – Frank van Puffelen May 13 '21 at 16:34
  • My understanding was that it only proactively refreshes the token if you are using realtime database or firestore in conjunction with firebase authentication. Is this behaviour documented somewhere? I am not alone with this impression it seems: https://stackoverflow.com/a/49697718/1386873 – puelo May 13 '21 at 17:06
  • 1
    Ah, I did not know that, but bojeil is definitely the authority in this. I always use at least one of the other Firebase services, so that would explain why I never get an expired token. If OP doesn't they might indeed have to force a token refresh in that case. I'd recommend not doing that for every call though, and instead caching the ID token for some time, similar to what the Firebase SDKs do. – Frank van Puffelen May 13 '21 at 17:41
  • Yeah. I think this could be documented a bit better. Thanks for the edit! – puelo May 13 '21 at 17:44
  • @puelo Thanks, that really clear things up. So I am using Vue and axios to work with my back-end. Is it a good idea to perform axios intercept every request and call `user.getIdToken()` and send that token. As I have noticed `getIdToken()` won't make a request to Firebase if it is not expired. Or maybe setup a datetime to check when the last `getIdToken()` was called and if it is about to expire (say half an hour) call `getIdToken()` again? – Msw Tm May 15 '21 at 15:40
  • 1
    I would probably just call `getIdToken` before each request. – puelo May 16 '21 at 12:40