CBOR Web Token (CWT)
RFC 8392 CBOR Web Token — the CBOR-native counterpart to JWT, a signed claims set for constrained / IoT, FIDO attestation, and verifiable-credential contexts. A CWT is a COSE_Sign1 (b.cose) whose payload is a deterministically-encoded CBOR claims map (b.cbor) — this module composes both and layers the standard-claim handling on top.
b.cwt.sign(claims, opts) accepts a friendly claims object; the standard claims are mapped to their RFC 8392 §3.1.1 integer labels (iss=1, sub=2, aud=3, exp=4, nbf=5, iat=6, cti=7) and any other key is kept verbatim. b.cwt.verify(cwt, opts) verifies the COSE signature (delegating the mandatory algorithm allowlist to b.cose.verify), decodes the claims, and enforces the time + identity claims: a passed exp, a future nbf, an iss / aud mismatch against the expected values are each refused.
Signing algorithms follow b.cose: the classical ES256/384/512 + EdDSA (final COSE ids, interoperable today) and ML-DSA-87 (PQC-forward). The optional CWT CBOR tag (61, RFC 8392 §6) wraps the COSE_Sign1 when opts.tagged is set; verify accepts tagged and untagged input.
b.cwt.sign(claims, opts) #
{
{
alg: string, // COSE signing alg (ES256 / EdDSA / ML-DSA-87 / …)
privateKey: object, // signing key (per b.cose.sign)
kid?: string, // COSE kid header
tagged?: boolean, // wrap in CWT CBOR tag 61 (default false)
externalAad?: Buffer, // bound into the COSE signature
}
}
Sign a claims set into a CWT (a COSE_Sign1 over the CBOR-encoded claims). Standard claims are mapped to their integer labels; custom claims (string or integer keys) are kept as given. exp / nbf / iat must be integer NumericDates (seconds since the epoch).
var cwt = await b.cwt.sign(
{ iss: "issuer.example", sub: "device-42", exp: Math.floor(Date.now()/1000) + 3600, scope: "telemetry" },
{ alg: "ES256", privateKey: ecKey, kid: "k1" });
b.cwt.verify(cwt, opts) #
{
{
algorithms: string[], // required — accepted COSE algs (allowlist)
publicKey?: object, // verification key (per b.cose.verify)
keyResolver?: function,
expectedIssuer?: string, // require iss === this
expectedAudience?: string, // require aud to include this
clockSkewSec?: number, // default 60
now?: number, // override clock (ms) for testing
externalAad?: Buffer,
}
}
Verify a CWT and return its claims. The COSE signature is checked via b.cose.verify (mandatory algorithms allowlist), then the standard time / identity claims are enforced: a passed exp (with clockSkewSec tolerance), a not-yet-valid nbf, and — when requested — an iss / aud mismatch are refused. Accepts a CWT-tag-61-wrapped or bare COSE_Sign1.
var out = await b.cwt.verify(cwt, { algorithms: ["ES256"], publicKey: pub, expectedIssuer: "issuer.example" });
// → { claims: { iss, sub, exp, scope }, raw: Map, protectedHeaders: Map }
Last updated 2026-08-08T16:39:49.652Z by seeder.