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
algheader matches the expected key encryption algorithm - Token’s
encheader matches the expected content encryption algorithm - Each key’s
usefield (if set) isEncrypting - Each key’s
key_opsfield (if set) includesDecryptorUnwrapKey
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
-
PeekHeaders( alg: algorithm.KeyEncryptionAlg, enc: algorithm.ContentAlg, kid: option.Option(String), )
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:
- Token’s
algandencheaders match the decryptor’s expected algorithms - Decryption succeeds with one of the decryptor’s keys
- Claims pass validation (exp, nbf, iss, aud per options)
When multiple keys are configured:
- Keys with matching
kidare tried first (if token haskidheader) kid_policycontrols kid header enforcement (seeKidPolicytype)- 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.