Skip to content

Instantly share code, notes, and snippets.

@saboyutaka
Last active February 27, 2021 07:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saboyutaka/940acb8c4188234323791c08f9063643 to your computer and use it in GitHub Desktop.
Save saboyutaka/940acb8c4188234323791c08f9063643 to your computer and use it in GitHub Desktop.
Decode Firebase Authentication JWT Token
export type firebasePublicKeys = {
[key: string]: string | undefined;
};
type JwtHeader = {
alg?: string | undefined;
kid?: string | undefined;
typ?: string | undefined;
};
const isObject = (thing: any): boolean => {
return Object.prototype.toString.call(thing) === '[object Object]';
};
const safeJsonParse = (thing: any): object | undefined => {
if (isObject(thing)) return thing;
try {
return JSON.parse(thing);
} catch (e) {
return undefined;
}
};
const getKidFromToken = (token: string): string | undefined => {
const jwtParts = token.split('.');
if (jwtParts.length !== 3) {
throw new Error('invalid jwt token');
}
const jwtHeader = jwtParts[0];
const decodedHeader = safeJsonParse(Buffer.from(jwtHeader, 'base64').toString('binary')) as JwtHeader | undefined;
return decodedHeader?.kid;
};
export const getPublickKey = (token: string, publicKeys: firebasePublicKeys): string => {
const kid = getKidFromToken(token);
if (!kid) {
throw new Error('jwt malformed');
}
return publicKeys[kid] || '';
};
import { getPublickKey, firebasePublicKeys } from './firebase';
import { getClaimFromToken } from './jwt_token';
import axios from 'axios';
const token = 'YOUR_TOKEN';
const audience = 'YOUR_AUDIENCE';
const url = 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com';
axios.get<firebasePublicKeys>(url).then(res => {
const firebasePublicKeys = res.data;
const publicKey = getPublickKey(token, firebasePublicKeys);
const claim = getClaim(token, publicKey, audience);
console.log(claim);
});
import { verify, JsonWebTokenError } from 'jsonwebtoken';
type JwtClaim = {
iss?: string | undefined;
aud?: string | undefined;
sub?: string | undefined;
iat?: number | undefined;
exp?: number | undefined;
};
export const getClaim = (token: string, publicKey: string, audience: string): JwtClaim | undefined => {
let claim;
verify(token, publicKey, { audience }, (err, decoded: JwtClaim | undefined) => {
if (err) throw new JsonWebTokenError(err.message);
claim = decoded;
});
return claim;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment