Files
skills/docs/security-stack/security/jws/src/header/header.md
2026-05-29 08:20:56 +01:00

2.8 KiB

header

(no submodules)

Purpose

Parse and serialise RFC 7515 §4.1 JOSE protected headers. Every registered parameter (alg, jku, jwk, kid, x5u, x5c, x5t, x5t#S256, typ, cty, crit, plus RFC 7797 b64) is shape-validated through the Zod schema; non-registered parameters survive round-trip via the schema's catch-all. The alg field is the only mandatory parameter; everything else is optional and the decoder preserves bytes verbatim so callers can re-emit the header without canonicalisation surprises.

Features

  • parseHeader(base64urlString | object) — base64url-decode + JSON-parse + Zod-shape-check; returns a typed JoseHeader.
  • serializeHeader(header) — JSON.stringify + base64url-encode in one call.
  • JoseHeader — strongly-typed shape (every registered parameter).
  • Unknown parameters survive round-trip.

Usage: Basic Example

import { parseHeader, serializeHeader } from "@suaveplan/jws";

const decoded = parseHeader("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9");
// { alg: "HS256", typ: "JWT" }

const reencoded = serializeHeader(decoded);

Usage: Advanced Example

import { JwsError, parseHeader } from "@suaveplan/jws";

try {
    parseHeader("eyJhbGciOjQyfQ"); // alg as number
} catch (err) {
    if (err instanceof JwsError && err.code === "JWS.HEADER_MALFORMED") {
        // The Zod boundary refused a non-string alg.
    }
}

// Custom parameter survives round-trip:
const h = parseHeader({ alg: "ES256", custom: { tenant: "acme" } });
console.log(h["custom"]); // { tenant: "acme" }

API Reference

  • parseHeader(input: string | Record<string, unknown>): JoseHeader
    • Decodes a base64url-encoded JSON object header, OR validates an already-parsed object.
    • Throws JwsError(JWS.HEADER_MALFORMED) on shape failure.
    • Throws JwsError(JWS.BASE64URL_INVALID) on base64url failure.
  • serializeHeader(header: JoseHeader | Record<string, unknown>): string
  • interface JoseHeader — every RFC 7515 §4.1 registered parameter, all readonly.

Implementation Notes

The schema is .passthrough() so consumers retain non-registered parameters — required for downstream RFCs (RFC 7519 JWT, RFC 9202 EAT-JWT, custom tenant claims) that layer additional parameters into the same header structure. Encoding always uses JSON.stringify with no replacer, which means insertion order is preserved; callers needing canonical-order headers (e.g. for byte-identical reproduction of an upstream signer's output) should sort their object keys before passing in. The decoder uses a strict UTF-8 TextDecoder so malformed UTF-8 sequences fail rather than silently inserting replacement characters into the parsed JSON — a deliberate strictness that catches producers that emit windows-1252 or latin-1 bytes through a misconfigured pipeline.