gose/encrypted_jwt
Encrypted JWT (JWE-based) - RFC 7519
This module provides encrypted JWT functionality built on top of JWE. Encrypted JWTs protect the claims payload through encryption rather than just signing, ensuring confidentiality in addition to integrity.
Use peek_headers() to inspect a token’s headers without decrypting.
Use decrypt_and_validate() to
decrypt and validate, producing a EncryptedJwt whose claims can be
trusted.
Example
import gleam/dynamic/decode
import gleam/time/duration
import gleam/time/timestamp
import gose/encrypted_jwt
import gose/jwa
import gose/jwk
import gose/jwt
let key = jwk.generate_enc_key(jwa.AesGcm(jwa.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, jwa.JweDirect, jwa.AesGcm(jwa.Aes256), key)
let token = encrypted_jwt.serialize(encrypted)
// Decrypt and validate using Decryptor (enforces algorithm pinning)
let assert Ok(decryptor) = encrypted_jwt.key_decryptor(
jwa.JweDirect, jwa.AesGcm(jwa.Aes256), [key], jwt.default_validation())
let assert Ok(verified) = encrypted_jwt.decrypt_and_validate(decryptor, token, now)
// Decode verified claims
let decoder = decode.field("sub", decode.string, decode.success)
let assert Ok(subject) = encrypted_jwt.decode(verified, 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 plaintext claims are available and have been validated.
This type is produced by decrypt_and_validate() after successful
decryption and claim verification.
pub opaque type EncryptedJwt
Header fields from an encrypted JWT token, extracted without decrypting.
pub type PeekHeaders {
PeekHeaders(
alg: jwa.JweAlg,
enc: jwa.Enc,
kid: option.Option(String),
)
}
Constructors
-
PeekHeaders( alg: jwa.JweAlg, enc: jwa.Enc, kid: option.Option(String), )
Values
pub fn alg(jwt: EncryptedJwt) -> jwa.JweAlg
Get the key encryption algorithm (alg) from a verified encrypted JWT.
Parameters
jwt- The verified encrypted JWT.
Returns
The JweAlg from the token’s header.
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.
Parameters
decryptor- ADecryptorcreated bykey_decryptororpassword_decryptor.token- The JWE compact serialization string.
Returns
Ok(EncryptedJwt) with the decrypted JWT and accessible
claims, Error(JweAlgorithmMismatch(_)) if the token’s algorithms
don’t match, or Error(DecryptionFailed(_)) if decryption fails.
pub fn decode(
jwt: EncryptedJwt,
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.
Parameters
jwt- A verified (decrypted) encrypted JWT.decoder- Agleam/dynamic/decodedecoder for the claims.
Returns
Ok(a) with the decoded claims value, or
Error(ClaimDecodingFailed(_)) if decoding fails.
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
Parameters
decryptor- ADecryptorcreated bykey_decryptororpassword_decryptor.token- The JWE compact serialization string.now- The current timestamp for time-based claim validation.
Returns
Ok(EncryptedJwt) with the decrypted and validated JWT,
Error(JweAlgorithmMismatch(_)) if the token’s algorithms don’t match
the decryptor’s expected algorithms, Error(DecryptionFailed(_)) if
decryption fails, or a claim validation error (TokenExpired,
TokenNotYetValid, etc.) if claim validation fails.
pub fn enc(jwt: EncryptedJwt) -> jwa.Enc
Get the content encryption algorithm (enc) from a verified encrypted JWT.
Parameters
jwt- The verified encrypted JWT.
Returns
The Enc from the token’s header.
pub fn encrypt_with_key(
claims: jwt.Claims,
alg: jwa.JweAlg,
enc: jwa.Enc,
key key: jwk.Jwk,
) -> 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 instead.
Sets typ: "JWT" in the header. If the encryption key has a kid, it is
included in the JWE header.
Parameters
claims- The JWT claims to encrypt.alg- The key encryption algorithm.enc- The content encryption algorithm.key- The encryption key.
Returns
Ok(EncryptedJwt) with the encrypted JWT ready for
serialization, or Error(JoseError(_)) if key validation or encryption
fails.
pub fn encrypt_with_password(
claims: jwt.Claims,
alg: jwa.Pbes2Alg,
enc: jwa.Enc,
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.
Parameters
claims- The JWT claims to encrypt.alg- The PBES2 algorithm.enc- The content encryption algorithm.password- The password for key derivation.kid- Optional key ID to include in the header.
Returns
Ok(EncryptedJwt) with the encrypted JWT ready for
serialization, or Error(JoseError(_)) if encryption fails.
pub fn key_decryptor(
alg: jwa.JweAlg,
enc: jwa.Enc,
keys keys: List(jwk.Jwk),
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.
Parameters
alg- The expected key encryption algorithm.enc- The expected content encryption algorithm.keys- One or more keys for decryption.options- Validation options for JWT claims.
Returns
Ok(Decryptor) configured and ready for use with
decrypt_and_validate, or Error(JoseError(_)) if the key list is
empty, any key’s use field is set but not Encrypting, or any key’s
key_ops doesn’t include Decrypt or UnwrapKey.
pub fn kid(jwt: EncryptedJwt) -> Result(String, Nil)
Get the key ID (kid) from a verified 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.
Parameters
jwt- The verified encrypted JWT.
Returns
Ok(String) with the key ID, or Error(Nil) if no kid was set.
pub fn password_decryptor(
alg: jwa.Pbes2Alg,
enc: jwa.Enc,
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.
Parameters
alg- The expected PBES2 algorithm.enc- The expected content encryption algorithm.password- The password for key derivation.options- Validation options for JWT claims.
Returns
A Decryptor configured for use with decrypt_and_validate.
pub fn peek_headers(
token: String,
) -> Result(PeekHeaders, jwt.JwtError)
Peek at the header fields from a token without decrypting.
Parameters
token- The JWE compact serialization string.
Returns
Ok(PeekHeaders) with the algorithm, encryption, and optional key ID
from the header, or Error(MalformedToken(_)) if the token cannot be
parsed.
pub fn serialize(jwt: EncryptedJwt) -> String
Serialize a decrypted encrypted JWT to compact format.
Parameters
jwt- AEncryptedJwtfromencrypt_with_key,encrypt_with_password, ordecrypt_and_validate.
Returns
The JWE compact serialization string.