48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
export type PlatformUser = {
|
|
sub: string
|
|
email: string
|
|
name: string
|
|
firstName: string
|
|
}
|
|
|
|
function decodeBase64Url(input: string): string {
|
|
const base64 = input.replace(/-/g, "+").replace(/_/g, "/")
|
|
const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), "=")
|
|
return Buffer.from(padded, "base64").toString("utf8")
|
|
}
|
|
|
|
export function decodeJwtPayload(token: string): Record<string, unknown> | null {
|
|
const parts = token.split(".")
|
|
if (parts.length !== 3 || !parts[1]) return null
|
|
try {
|
|
return JSON.parse(decodeBase64Url(parts[1])) as Record<string, unknown>
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
export function platformUserFromToken(token: string): PlatformUser | null {
|
|
const claims = decodeJwtPayload(token)
|
|
if (!claims) return null
|
|
|
|
const sub = typeof claims.sub === "string" ? claims.sub : null
|
|
const email =
|
|
(typeof claims.email === "string" && claims.email) ||
|
|
(typeof claims.preferred_username === "string" && claims.preferred_username) ||
|
|
null
|
|
if (!sub || !email) return null
|
|
|
|
const name =
|
|
(typeof claims.name === "string" && claims.name) ||
|
|
(typeof claims.given_name === "string" && claims.given_name) ||
|
|
email.split("@")[0] ||
|
|
email
|
|
|
|
const firstName =
|
|
(typeof claims.given_name === "string" && claims.given_name) ||
|
|
name.split(/\s+/)[0] ||
|
|
name
|
|
|
|
return { sub, email, name, firstName }
|
|
}
|