gose/jose/encrypted_jwt

Encrypted JWT (JWE-based) - RFC 7519

Encrypted JWTs built on JWE protect the claims payload through encryption, providing confidentiality and ciphertext integrity. Encryption alone does not authenticate the issuer. For asymmetric algorithms (RSA-OAEP, ECDH-ES), anyone with the recipient’s public key can produce a valid encrypted token.

If your application requires proof of origin, use sign-then-encrypt (nested JWT): sign the claims with JWS first, then encrypt the signed token with JWE.

Use peek_headers() to inspect a token’s headers without decrypting. Use decrypt_and_validate() to decrypt and validate claim fields (exp, nbf, iss, aud), producing an EncryptedJwt whose claims have been decrypted and validated.

Example

import gleam/dynamic/decode
import gleam/time/duration
import gleam/time/timestamp
import gose/jose/encrypted_jwt
import gose/algorithm
import gose/key
import gose/jose/jwt

let key = key.generate_enc_key(algorithm.AesGcm(algorithm.Aes256))
let now = timestamp.system_time()

// Create claims and encrypt
let claims = jwt.claims()
  |> jwt.with_subject("user123")
  |> jwt.with_issuer("my-app")
  |> jwt.with_expiration(timestamp.add(now, duration.hours(1)))

let assert Ok(encrypted) = encrypted_jwt.encrypt_with_key(
  claims, algorithm.Direct, algorithm.AesGcm(algorithm.Aes256), key)
let token = encrypted_jwt.serialize(encrypted)

// Decrypt and validate using Decryptor (enforces algorithm pinning)
let assert Ok(decryptor) = encrypted_jwt.key_decryptor(
  algorithm.Direct, algorithm.AesGcm(algorithm.Aes256), [key], jwt.default_validation())
let assert Ok(decrypted) = encrypted_jwt.decrypt_and_validate(decryptor, token, now)

// Decode decrypted and validated claims
let decoder = decode.field("sub", decode.string, decode.success)
let assert Ok(subject) = encrypted_jwt.decode(decrypted, decoder)

Types

A decryptor that pins the expected algorithms and validates keys.

Create with key_decryptor() or password_decryptor(). The decryptor validates that:

  • Token’s alg header matches the expected key encryption algorithm
  • Token’s enc header matches the expected content encryption algorithm
  • Each key’s use field (if set) is Encrypting
  • Each key’s key_ops field (if set) includes Decrypt or UnwrapKey
pub opaque type Decryptor

A JWT whose claims have been decrypted and whose claim fields (exp, nbf, iss, aud) have been validated. Produced by decrypt_and_validate(). Note that encryption provides confidentiality, not issuer authentication.

pub opaque type EncryptedJwt

Header fields from an encrypted JWT token, extracted without decrypting.

pub type PeekHeaders {
  PeekHeaders(
    alg: algorithm.KeyEncryptionAlg,
    enc: algorithm.ContentAlg,
    kid: option.Option(String),
  )
}

Constructors

Values

pub fn alg(jwt: EncryptedJwt) -> algorithm.KeyEncryptionAlg

Get the key encryption algorithm (alg) from a decrypted and validated encrypted JWT.

pub fn dangerously_decrypt_and_skip_validation(
  decryptor: Decryptor,
  token: String,
) -> Result(EncryptedJwt, jwt.JwtError)

Decrypt an encrypted JWT, skipping all claim validation.

Warning: This skips expiration, not-before, issuer, and audience checks. Use only when you have a legitimate reason to bypass validation, such as inspecting claims before deciding on validation policy.

Still enforces algorithm pinning for security. Note: kid_policy only applies to key-based decryptors, not password-based decryptors.

pub fn decode(
  jwt: EncryptedJwt,
  using decoder: decode.Decoder(a),
) -> Result(a, jwt.JwtError)

Decode an encrypted JWT’s claims using a custom decoder.

This allows extracting claims directly into your own types using gleam/dynamic/decode. The decoder receives the raw claims JSON.

pub fn decrypt_and_validate(
  decryptor: Decryptor,
  token: String,
  now now: timestamp.Timestamp,
) -> Result(EncryptedJwt, jwt.JwtError)

Decrypt an encrypted JWT and validate its claims using a Decryptor.

Checks:

  1. Token’s alg and enc headers match the decryptor’s expected algorithms
  2. Decryption succeeds with one of the decryptor’s keys
  3. Claims pass validation (exp, nbf, iss, aud per options)

When multiple keys are configured:

  • Keys with matching kid are tried first (if token has kid header)
  • kid_policy controls kid header enforcement (see KidPolicy type)
  • With NoKidRequirement, all keys are tried with matching keys prioritized
pub fn enc(jwt: EncryptedJwt) -> algorithm.ContentAlg

Get the content encryption algorithm (enc) from a decrypted and validated encrypted JWT.

pub fn encrypt_with_key(
  claims: jwt.Claims,
  alg alg: algorithm.KeyEncryptionAlg,
  enc enc: algorithm.ContentAlg,
  key key: key.Key(String),
) -> Result(EncryptedJwt, jwt.JwtError)

Encrypt claims using a key-based algorithm.

Supports all key-based JWE algorithms: direct symmetric (dir), AES Key Wrap, AES-GCM Key Wrap, RSA-OAEP, and ECDH-ES. PBES2 password-based algorithms return an error. Use encrypt_with_password for those.

Sets typ: "JWT" in the header. If the encryption key has a kid, it is included in the JWE header.

pub fn encrypt_with_password(
  claims: jwt.Claims,
  alg alg: algorithm.Pbes2Alg,
  enc enc: algorithm.ContentAlg,
  password password: String,
  kid kid: option.Option(String),
) -> Result(EncryptedJwt, jwt.JwtError)

Encrypt claims using PBES2 password-based encryption.

Sets typ: "JWT" in the header.

pub fn key_decryptor(
  alg alg: algorithm.KeyEncryptionAlg,
  enc enc: algorithm.ContentAlg,
  keys keys: List(key.Key(String)),
  options options: jwt.JwtValidationOptions,
) -> Result(Decryptor, jwt.JwtError)

Create a key-based decryptor for symmetric (dir, AES-KW, AES-GCM-KW) or asymmetric (RSA-OAEP, ECDH-ES) algorithms.

The decryptor pins the expected algorithms. Tokens with different algorithms will be rejected.

pub fn kid(jwt: EncryptedJwt) -> Result(String, Nil)

Get the key ID (kid) from a decrypted and validated encrypted JWT header.

Security Warning: The kid value comes from the token and is untrusted input. If you use it to look up keys (from a database, filesystem, or key store), you must sanitize it first to prevent injection attacks.

pub fn password_decryptor(
  alg alg: algorithm.Pbes2Alg,
  enc enc: algorithm.ContentAlg,
  password password: String,
  options options: jwt.JwtValidationOptions,
) -> Decryptor

Create a password-based decryptor for PBES2 algorithms.

The decryptor pins the expected algorithms. Tokens with different algorithms will be rejected.

pub fn peek_headers(
  token: String,
) -> Result(PeekHeaders, jwt.JwtError)

Peek at the header fields from a token without decrypting.

pub fn serialize(jwt: EncryptedJwt) -> String

Return the compact serialization of an encrypted JWT.

Search Document