UNPKG

@borderless/web-jwt

Version:

Small JWT library using the Web Crypto API

65 lines 2.25 kB
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