Firebase JWT Auth Tokens with Custom Expiration Time

Firebase Admin SDK libraries provide a function to generate a custom JSON Web Token (JWT) to authenticate users. The generated JWT expiration time is fixed to 60 minutes and Firebase doesn't allow tokens with a higher expiration time than 60 minutes.

But how can we generate tokens with a custom expiration time lesser than 60 minutes? Let's talk about a viable plan.

Anatomy of Firebase JWT

It's not a secret that you can decode any JWT and see the contents.

Try it on JWT

By looking at the decoded contents of the token, we can identify the payload properties responsible for tracking the expiry time. Specifically iat - (issued-at-time) and exp - (expiration time) are the keys that track the time of initialization and expiration in seconds since UNIX epoch.

firebase-jwt-anatomy.png

Let's Hack It

The official Admin SDK function to create custom tokens accept three arguments. Here developer_claims and tenant_id is optional. developer_claims is a dictionary where it accepts additional data to be encoded within the JWT generated.

create_custom_token(self, uid, developer_claims, tenant_id)

I tried to tweak the official Admin SDK function to create a custom token with a custom expiration time by passing the same dictionary keys iat and exp assuming that will replace the internally generated expiration values.

 custom_token = auth.create_custom_token('12345', {'iat': 48784, 'exp': 83733})

But the result wasn't successful at all. The official Admin SDK restricted that returning me an error.

ValueError: Developer claims iat, exp are reserved and cannot be specified.

The Decent Way

So the tweak didn't work as expected. We cannot do that with Firebase Admin SDK. But Firebase documentation suggests a third-party JWT library just in case there's no officially supported Admin SDK for a particular programming language.

Although that is the original intention to depend on a third-party JWT library to generate custom auth tokens. We can use it to create JWT with a custom expiration time. So here, we make use of PyJWT library in Python to generate a token from the scratch.

import jwt
import time

TOKEN_EXPIRATION_TIME_IN_MINUTES = 2

user_id = 'XXXXXXXXX'

# Refer your admin SDK credential JSON file to replace below values
service_account_email = "firebase-adminsdk-**@***.iam.gserviceaccount.com"
private_key = b"-----BEGIN PRIVATE KEY-----\n*****"

# Current time in seconds
current_time = int(time.time())

payload = {
     'iss': service_account_email,
     'sub': service_account_email,
     'aud': "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
     'iat': current_time,
     'exp': current_time + (TOKEN_EXPIRATION_TIME_IN_MINUTES*60),
     'uid': user_id
}

encoded_token = jwt.encode(payload, private_key, algorithm="RS256")

# Tokens are created as a binary. Decoding with utf-8 will convert it to a String 
jwt_token = encoded.decode("utf-8")

Token Refresh

Firebase tokens are created with a maximum of 60 minutes expiration time. You might wonder what happens after the time of token expiration. Should you worry about it?

In general scenarios, short-lived auth tokens are associated with long-lived refresh tokens to exchange for a new auth token when auth token expired. So, we should worry about the mechanism of acquiring a new auth token when it is expired.

But, Firebase client SDKs will handle this token exchange internally and keep you logged in for an indefinite time until a signout call. So, no need to worry about token management even a custom token generated via a third-party JWT library.