Last active
February 27, 2021 07:42
-
-
Save saboyutaka/940acb8c4188234323791c08f9063643 to your computer and use it in GitHub Desktop.
Decode Firebase Authentication JWT Token
This file contains 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
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] || ''; | |
}; |
This file contains 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 { 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/[email protected]'; | |
axios.get<firebasePublicKeys>(url).then(res => { | |
const firebasePublicKeys = res.data; | |
const publicKey = getPublickKey(token, firebasePublicKeys); | |
const claim = getClaim(token, publicKey, audience); | |
console.log(claim); | |
}); |
This file contains 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 { 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