in src/jwt.ts [93:150]
export function decomposeJwt(jwt: unknown): {
header: JwtHeader;
headerB64: string;
payload: JwtPayload;
payloadB64: string;
signatureB64: string;
} {
// Sanity checks on JWT
if (!jwt) {
throw new JwtParseError("Empty JWT");
}
if (typeof jwt !== "string") {
throw new JwtParseError("JWT is not a string");
}
if (!jwt.match(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/)) {
throw new JwtParseError(
"JWT string does not consist of exactly 3 parts (header, payload, signature)"
);
}
const [headerB64, payloadB64, signatureB64] = jwt.split(".");
// B64 decode header and payload
const [headerString, payloadString] = [headerB64, payloadB64].map((b64) =>
Buffer.from(b64, "base64").toString("utf8")
);
// Parse header
let header: ReturnType<typeof safeJsonParse>;
try {
header = safeJsonParse(headerString);
} catch (err) {
throw new JwtParseError(
"Invalid JWT. Header is not a valid JSON object",
err
);
}
assertJwtHeader(header);
// parse payload
let payload: ReturnType<typeof safeJsonParse>;
try {
payload = safeJsonParse(payloadString);
} catch (err) {
throw new JwtParseError(
"Invalid JWT. Payload is not a valid JSON object",
err
);
}
assertJwtPayload(payload);
return {
header,
headerB64,
payload,
payloadB64,
signatureB64,
};
}