@borderless/web-jwt
Version:
Small JWT library using the Web Crypto API
65 lines • 2.25 kB
JavaScript
import { decode, encodeUrl as encode } from "@borderless/base64";
/**
* JWT none algorithm support.
*/
export const NONE_KEY = Symbol("none");
const encoder = new TextEncoder();
const decoder = new TextDecoder();
/**
* Decode results for invalid JWTs.
*/
export const NOOP_JWT = {
header: {},
payload: {},
data: new Uint8Array(0),
signature: new Uint8Array(0),
};
/**
* Decode the JWT using base64url and JSON.
*/
export function decodeJwt(token) {
try {
const parts = token.split(".", 4);
if (parts.length !== 3)
return NOOP_JWT;
const header = JSON.parse(decoder.decode(decode(parts[0])));
const payload = JSON.parse(decoder.decode(decode(parts[1])));
const signature = decode(parts[2]);
// Sanity check JWT shape.
if (header !== null &&
typeof header === "object" &&
(header.typ === undefined || header.typ === "JWT") &&
(header.alg === undefined || typeof header.alg === "string") &&
(header.kid === undefined || typeof header.kid === "string") &&
payload !== null &&
typeof payload === "object") {
const data = encoder.encode(`${parts[0]}.${parts[1]}`);
return { header, payload, data, signature };
}
}
catch {
// Noop.
}
return NOOP_JWT;
}
/**
* Verify the JWT contents by deriving the signature from the content.
*/
export async function verifyJwt(raw, key) {
if (key === NONE_KEY)
return raw.signature.length === 0; // Support alg none.
return crypto.subtle.verify(key.algorithm, key, raw.signature, raw.data);
}
/**
* Stringify a JWT payload and sign using crypto key.
*/
export async function encodeJwt(header, payload, key) {
const rawHeader = encode(encoder.encode(JSON.stringify(header)));
const rawPayload = encode(encoder.encode(JSON.stringify(payload)));
if (key === NONE_KEY)
return `${rawHeader}.${rawPayload}.`; // Support alg none.
const data = encoder.encode(`${rawHeader}.${rawPayload}`);
const signature = await crypto.subtle.sign(key.algorithm, key, data);
return `${rawHeader}.${rawPayload}.${encode(signature)}`;
}
//# sourceMappingURL=index.js.map