# @codenhub/jwt

> JwtKit: JSON Web Token (compact JWS) signing and verification, JWK import and export, key generation, and key sets on Web Crypto, for tokens that must be treated as untrusted. Supports ES256, EdDSA, Ed25519, RS256, PS256 and HS256; `none` is never accepted. No runtime dependencies; runs on Node.js 24 or newer, browsers and edge runtimes. The package is experimental.

Every key is bound to exactly one algorithm when it is generated (`generateKeyPair`, `generateSecretKey`) or imported (`importPublicKey`, `importPrivateKey`, `importSecretKey`); a token verifies only with a key whose `alg` equals its header's `alg`. Keys are opaque frozen objects (`kind` is `public`, `private` or `secret`); only objects this package created are accepted, and only by the same copy of the package, so a program must load one copy (dedupe the install; a library built on it declares it as a `peerDependency`). `createVerifier({ keys, issuer, audience, type, clockTolerance, maxAge, maxLength, requiredClaims, claims, now })` returns `verify(token)`, which resolves to `{ ok: true, value: { header, payload, key } }` or `{ ok: false, error: { issues } }` and never throws for a token; only a `claims` schema that throws or rejects makes it reject. Durations are seconds; `now` returns milliseconds. Checks run in order: length cap (default 8192), strict base64url and JSON (duplicate keys rejected, depth 32), supported `alg`, no `crit`, key selection, signature, then claims (all claim failures reported together), then the optional Standard Schema `claims`. There is no unverified payload decode; `readHeader(token)` returns only the header. `sign({ payload, key, header })` takes `alg` from the key and adds no claims. Key sets: `createKeySet(keys)`, `importKeySet(jwks, { algorithms })`, and `createRemoteKeySet({ url, cacheTtl, cooldown, maxStale, timeout, maxResponseBytes, fetch })` for an https JWKS URL with caching, a refetch on unknown `kid` limited by a cooldown, and stale keys while the issuer is unreachable. Selection never tries keys in turn. Issues have a stable `code`, optional `path` and `params`, and the package's own issues never contain input values; a `claims` schema's path may name payload properties, and a custom key set's issues are passed through. Invalid options and foreign key objects throw `TypeError`.

## Documentation

- [Documentation overview](docs/index.md): What a JWT is, algorithm binding, the result shape, the check order, and requirements.
- [Verifying tokens](docs/verifying.md): Every `createVerifier` option, check order, time claims and clock tolerance, audience and `typ` matching, Standard Schema claims, and `readHeader`.
- [Signing tokens](docs/signing.md): What `sign` writes into the header, refused header parameters, and the payload rules.
- [Keys](docs/keys.md): Key kinds, generating, importing JWKs and raw secrets with the checks and issues of each, and exporting.
- [Key sets](docs/key-sets.md): Selection rules, local sets, importing a JWKS, and remote JWKS caching, cooldown, stale keys and fetch failures.
- [Issues](docs/errors.md): The result shape and every issue code with its path and params, and what throws instead.
