18

I have used "signInWithCustomToken()" to authenticate firebase user.

This token expires in 1 hour.

Firebase has recommended token expiration to 1 hour. If we modify the expiry while creating custom token using "php-jwt" library, firebase throws exception "The custom token format is incorrect. Please check the documentation".

While searching for solutions, I found following thread- "Firebase Android Authentication failed: expired_token (Auth token is expired)"

But refreshed token returned by "onTokenRefresh()" doesn't work for me.

What will be the procedure to refresh this custom token?

OR

Is there a way to set manual expiry to custom token?

Community
  • 1
  • 1
Varsha P
  • 311
  • 1
  • 3
  • 13

4 Answers4

20

There is a limitation with the Firebase custom token generation. Firebase custom auth token is limited to max 1Hr(3600sec).

exp The time, in seconds, at which the token expires. It can be at a maximum 3600 seconds later than iat.

If auth token expires every hour, its difficult for us to maintain the valid session all the time :(

When we use default Auth providers like (Google, Facebook, Email..); Firebase SDK will take care of refreshing your Auth token by default. But in custom authentication, Firebase SDK need to contact 3rd party server to fetch new token. Here only SDK is failing to refresh the token!

My workaround is, maintain a "last-token-fetch-time" info at local on every successful token fetch, so that we can refresh the token manually after one hour.

You can refer this issue log for more info,

  1. https://github.com/firebase/quickstart-android/issues/31
  2. In Firebase 9.0.0 API, how to check the user has valid Auth session or not?

Update:

Google updated their document,

exp (Expiration time): The time, in seconds since the UNIX epoch, at which the token expires. It can be a maximum of 3600 seconds later than the iat. (Note: this only controls the time when the custom token itself expires. But once you sign a user in using signInWithCustomToken(), they will remain signed in into the device until their session is invalidated or the user signs out.)

As document says, custom JWT token is valid for max 1Hr; so before it expires, authenticate your user with Firebase. After that session will remain active; It wont expire!

You can use below method to ensure that user has valid session,

public static boolean hasValidAuthToken() {
    return FirebaseAuth.getInstance().getCurrentUser() != null ? true : false;
}

Hope this would help you!

wonsuc
  • 3,498
  • 1
  • 27
  • 30
Karthi R
  • 1,338
  • 10
  • 25
  • Yes definitely it helped. But refreshing the token manually after every 1 hour might not be the worth solution. (Server call after every 1hour can degrade the app performance.) Hope that Firebase may give the alternative to it soon. – Varsha P Jul 14 '16 at 06:51
  • Till then to try this solution, how to refresh or verify the token at server side? _I have used php-jwt library._ – Varsha P Jul 14 '16 at 06:58
  • 1
    You can create an endpoint at your server-side to issue a "custom Auth token" for every client request. For more info, you can refer this doc [How to create custom token at your server](https://firebase.google.com/docs/auth/server/create-custom-tokens) – Karthi R Jul 14 '16 at 07:36
  • 1
    Are you sure of "authenticate your user with Firebase. After that session will remain active; It wont expire!" Do you have any official documentation for that? – Muhammad Hassan Nasr Sep 28 '16 at 12:39
  • @MuhammadHassan you can refer the [official doc](https://firebase.google.com/docs/auth/server/create-custom-tokens). "Custom Token Claims" > "exp" – Karthi R Sep 28 '16 at 13:37
  • @KarthiR, thanks for the link, it is said that "they will remain signed in into the device until their session is invalidated" when can the session be invalidated? – Muhammad Hassan Nasr Sep 29 '16 at 18:14
  • @MuhammadHassan, You can use the above 'hasValidAuthToken()' to ensure the user has valid session. – Karthi R Sep 30 '16 at 00:58
  • @KarthiR Thanks for the tip. Actually I want to make authentication like whatsapp, which verifies user phone number once and keep him signed in for at-least one year (whether app is closed, in the background, ...). Can we do that with firebase custom token? – Muhammad Hassan Nasr Jan 18 '17 at 08:12
  • 1
    @MuhammadHassan, I believe; yes you can go with custom token. After successful authentication with Firebase, SDK will take care of maintaining your session. – Karthi R Jan 18 '17 at 11:32
  • Does the same happen for web SDK? – Muhammad Hassan Nasr Jan 19 '17 at 18:09
  • @MuhammadHassan; Hope it will be same for web – Karthi R Jan 23 '17 at 07:49
9

The SDK will take care of keeping the tokens up to date IF YOU ARE SETUP correctly. For more info The custom tokens are only used to start a SESSION. So you have to have hour to use a custom token to SIGN IN. Once you are signed in and your Firebase Admin account and app configuration is setup correctly, the SDK can communicate back and forth with the Firebase back-end to keep the tokens up to date. Once you sign out with FirebaseAuth.signout(), you will need a new custom token to sign back in if it has been over 1 hour.

Jeremy House
  • 141
  • 1
  • 3
  • So, when we generate the custom token on server side, pass it to the app, sign in and start/close the app 100... times in e.g. one year, then until the signed out process, the token will be updated by Firebase automatically? – H.Karatsanov Jun 25 '20 at 14:16
0

Something like this is a way to check the Token and see if its expired. You can then mint a new one

public async Task<string> GetIdTokenAsync()
{
  // Get current time in seconds from Epoch
  var secondsSinceEpoch = DateTimeOffset.UtcNow.ToUnixTimeSeconds();

  // We have already minted a token for this session, so check if we need a new one 
  if (this.idToken != null)
  {
    // Check to see if current token is expired or will expire soon
    var idTokenExpiration = JwtDecoder.TokenExpirationTime(this.idToken);
    if (idTokenExpiration > (secondsSinceEpoch - 60L))
    {
      return this.idToken;
    }
  }

  // No id token for this session, or we have an id token, but its expired, so mint a new one
  this.idToken = await auth?.CurrentUser?.GetIdTokenAsync(true);
  return this.idToken;
}
stepheaw
  • 1,683
  • 3
  • 22
  • 35
-7

You can get refreshed token using this code

FirebaseInstanceId.getInstance().getToken();

FirebaseInstanceId is my Class Name change it according to you.

Harsh Patel
  • 1,056
  • 2
  • 10
  • 20
  • 1
    really, Is this the solution Varsha might be looking for ? – Chintan Soni Jul 13 '16 at 12:22
  • I have tried solution given in "http://stackoverflow.com/questions/37505119/firebase-android-authentication-failed-expired-token-auth-token-is-expired". But did not work for me. – Varsha P Jul 13 '16 at 12:45
  • @ChintanSoni given the mention of `onTokenRefresh()` in the question, having an answer with `FirebaseInstanceId` is not completely unexpected. Both are concepts from Firebase Cloud Messaging. What that has to do with Firebase Authentication is a good question, but one that OP will have to answer by providing an [MCVE](http://stackoverflow.com/help/mcve). – Frank van Puffelen Jul 19 '16 at 23:35