Created
June 11, 2020 08:45
-
-
Save juandebravo/d19989f7efbee38606a4929c55f46330 to your computer and use it in GitHub Desktop.
Firebase auth: change the custom token expiration time
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import functools | |
import datetime | |
import time | |
from firebase_admin import auth | |
import google.auth.exceptions | |
EXP_TIME_GENERIC_TOKEN = int(datetime.timedelta(minutes=15).total_seconds()) | |
RESERVED_CLAIMS = set([ | |
'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash', | |
'exp', 'firebase', 'iat', 'iss', 'jti', 'nbf', 'nonce', 'sub' | |
]) | |
FIREBASE_AUDIENCE = ('https://identitytoolkit.googleapis.com/google.' | |
'identity.identitytoolkit.v1.IdentityToolkit') | |
def _patch_create_custom_token(self, uid, developer_claims=None, tenant_id=None): | |
"""Builds and signs a Firebase custom auth token.""" | |
if developer_claims is not None: | |
if not isinstance(developer_claims, dict): | |
raise ValueError("developer_claims must be a dictionary") | |
disallowed_keys = set(developer_claims.keys()) & RESERVED_CLAIMS | |
if disallowed_keys: | |
if len(disallowed_keys) > 1: | |
error_message = ( | |
"Developer claims {0} are reserved and " | |
"cannot be specified.".format(", ".join(disallowed_keys)) | |
) | |
else: | |
error_message = ( | |
"Developer claim {0} is reserved and " | |
"cannot be specified.".format(", ".join(disallowed_keys)) | |
) | |
raise ValueError(error_message) | |
if not uid or not isinstance(uid, str) or len(uid) > 128: | |
raise ValueError("uid must be a string between 1 and 128 characters.") | |
# Let define the expiration time but make sure we don't add it as custom claim | |
expiration_time = developer_claims.pop( | |
"max_lifetime_seconds", EXP_TIME_GENERIC_TOKEN | |
) | |
signing_provider = self.signing_provider | |
now = int(time.time()) | |
payload = { | |
"iss": signing_provider.signer_email, | |
"sub": signing_provider.signer_email, | |
"aud": FIREBASE_AUDIENCE, | |
"uid": uid, | |
"iat": now, | |
"exp": now + expiration_time, | |
} | |
if tenant_id: | |
payload["tenant_id"] = tenant_id | |
if developer_claims is not None: | |
payload["claims"] = developer_claims | |
try: | |
return jwt.encode(signing_provider.signer, payload) | |
except google.auth.exceptions.TransportError as error: | |
msg = "Failed to sign custom token. {0}".format(error) | |
raise TokenSignError(msg, error) | |
def firebase_app(): | |
# implement your way to obtain the Firebase app properly initialized | |
return None | |
def create_custom_token( | |
uid, max_lifetime_seconds=EXP_TIME_GENERIC_TOKEN, **dev_claims: Dict[str, str] | |
): | |
fb_app = firebase_app() | |
token_generator = auth._get_client(app=fb_app)._token_generator | |
initial_create_custom_token = token_generator.create_custom_token | |
try: | |
my_create_custom_token = functools.partial( | |
_patch_create_custom_token, token_generator | |
) | |
token_generator.create_custom_token = my_create_custom_token | |
return auth.create_custom_token( | |
uid, | |
dict(max_lifetime_seconds=max_lifetime_seconds, **dev_claims), | |
app=fb_app, | |
) | |
finally: | |
token_generator.create_custom_token = initial_create_custom_token |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment