Initial Commit
This commit is contained in:
57
packages/security-stack/security/jws/src/header/header.md
Normal file
57
packages/security-stack/security/jws/src/header/header.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# `header`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## 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
|
||||
|
||||
```ts
|
||||
import { parseHeader, serializeHeader } from "@suaveplan/jws";
|
||||
|
||||
const decoded = parseHeader("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9");
|
||||
// { alg: "HS256", typ: "JWT" }
|
||||
|
||||
const reencoded = serializeHeader(decoded);
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user