For the complete documentation index, see llms.txt. This page is also available as Markdown.

Encryption (JWE)

Encrypt and decrypt JWTs using RSA-OAEP key wrap or direct symmetric encryption.

A JSON Web Encryption (JWE) token has its payload encrypted — even the issuer cannot read it without the decryption key. Use JWE when the claims contain sensitive data (PII, PHI, secrets) that must remain confidential in transit and at rest in client storage.

bx-jwt supports two encryption modes:

  • RSA-OAEP-256 + A256GCM — asymmetric key wrapping. Anyone with the RSA public key can encrypt; only the private-key holder can decrypt.

  • dir + A256GCM — direct symmetric encryption with a 256-bit (32-byte) shared key.

RSA Key Wrapping (Asymmetric)

keys = jwtGenerateKeyPair( "RS256" );  // 2048-bit RSA pair

// Encrypt with the public key (anyone can do this)
token = jwtEncrypt( { sub: "u1", ssn: "123-45-6789" }, keys.publicKey, {
    keyAlgorithm: "RSA-OAEP-256",
    encAlgorithm: "A256GCM"
} );

// Decrypt with the private key (only the holder can do this)
payload = jwtDecrypt( token, keys.privateKey, {
    keyAlgorithm: "RSA-OAEP-256",
    encAlgorithm: "A256GCM"
} );

This pattern is ideal when many producers must encrypt for a single consumer (e.g. a central service that receives sensitive payloads from many clients).

Direct Symmetric Encryption

When both ends of the conversation can hold the same secret, dir is faster and produces smaller tokens.

Nested JWT (Sign → Encrypt)

When you need both integrity (proof of issuer) and confidentiality (encrypted payload), sign the token first and then encrypt the result. The standard cty: "JWT" header tells consumers the JWE wraps a JWS.

Fluent Builder for JWE

The same fluent builder used for signing also produces JWEs — just call .encrypt() to terminate the chain:

Last updated

Was this helpful?