Jwt unstable
Signed or encrypted compact JSON Web Tokens whose claims are encoded and
decoded with a Schema.
Verification and decryption authenticate the token first, then check the
registered claims and the validation policy, and only then decode the
application claims. exp and nbf are checked whenever they are present;
require them with requiredClaims.
Bound untrusted token length before verification, decryption, or unverified decoding; this module does not impose a token-size limit.
Cryptography
Decrypts a compact dir/A256GCM JWT, checks its claims against the policy,
and decodes the claims with a schema.
Details
Accepts a key or an effectful resolver for key rotation. The same claim policy as verify is applied after authenticated decryption and before the application schema is decoded.
Gotchas
The resolver receives an unauthenticated header and must use it only for key selection.
See
Signature
declare const decrypt: <S extends Constraint, E = never, R = never>(...args: [schema: S, token: string | Redacted<string>, key: SecretKey<"dir"> | (header: { [key: string]: Json; readonly alg: "dir"; readonly cty?: string; readonly enc: "A256GCM"; readonly kid?: string; readonly typ?: string;}) => Effect<SecretKey<"dir">, E, R>, options?: VerifyOptions]) => Effect<Decrypted<S["Type"]>, JwtError | E, Aead | R | S["DecodingServices"]>Encodes claims with a schema and encrypts them as a compact dir/A256GCM
JWT.
Signature
declare function encrypt<S extends Constraint, H extends object & { [P in string | number | symbol]: Json | undefined } = Header>(schema: S, claims: S["Type"], key: SecretKey<"dir">, header?: Header & H): Effect<Redacted<string>, JwtError, Aead | SecureRandom | S["EncodingServices"]>Example Encrypting and validating application claims
import { Effect, Layer, Redacted, Schema } from "effect"import { Aead, SecureRandom } from "effect/crypto"import { Jwk, Jwt } from "effect/jose"
const layer = Aead.layerWebCrypto.pipe(Layer.provideMerge(SecureRandom.layerWebCrypto))const Claims = Schema.Struct({ sub: Schema.String })
const claims = await Effect.runPromise(Effect.gen(function*() { // Fixed public example material; generate application secrets securely. const key = yield* Jwk.importSecret( Redacted.make({ kty: "oct", k: "BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc" } as const), "dir" ) const token = yield* Jwt.encrypt(Claims, { sub: "user-123" }, key, { typ: "session+jwt" }) const decrypted = yield* Jwt.decrypt(Claims, token, key, { typ: "session+jwt" }) return decrypted.claims}).pipe(Effect.provide(layer)))claims // => ({ sub: "user-123" })Encodes claims with a schema and signs them as a compact JWT.
Signature
declare function sign<S extends Constraint, K extends SigningKey, H extends object & { [P in string | number | symbol]: Json | undefined } = Header>(schema: S, claims: S["Type"], key: K, header?: Header & H): Effect<Redacted<string>, JwtError, S["EncodingServices"] | KeyRequirements<K>>Verifies a compact JWT with a key, checks its claims against the policy, and decodes the claims with a schema.
See
- verifyWithKeySet for resolving the key from the
Jwksservice - decrypt for encrypted JWTs
Signature
declare const verify: <S extends Schema.Constraint, K extends VerificationKey>(schema: S, token: string | Redacted.Redacted<string>, key: K, options?: VerifyOptions) => Effect.Effect<Verified<S["Type"]>, JwtError, S["DecodingServices"] | Jws.KeyRequirements<K>>Example Verifying a token
import { Effect, Layer, Redacted, Schema } from "effect"import { Mac, SecureRandom, Signature } from "effect/crypto"import { Jwk, Jwt } from "effect/jose"
const layer = Layer.mergeAll(Mac.layerWebCrypto, Signature.layerWebCrypto).pipe( Layer.provide(SecureRandom.layerWebCrypto))
const Claims = Schema.Struct({ sub: Schema.String, iss: Schema.String })
const claims = await Effect.runPromise(Effect.gen(function*() { // Fixed public example material; generate application secrets securely. const key = yield* Jwk.importSecret( Redacted.make({ kty: "oct", k: "BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc" } as const), "HS256" ) const token = yield* Jwt.sign(Claims, { sub: "user-123", iss: "example" }, key) const verified = yield* Jwt.verify(Claims, token, key, { issuer: "example", requiredClaims: ["sub"] }) return verified.claims}).pipe(Effect.provide(layer)))claims // => ({ sub: "user-123", iss: "example" })verifyWithKeySet
unstableVerifies a compact JWT with a public key resolved from the Jwks service,
checks its claims against the policy, and decodes the claims with a schema.
See
- verify for verifying with a known key
Signature
declare const verifyWithKeySet: <S extends Schema.Constraint>(schema: S, token: string | Redacted.Redacted<string>, options: VerifyWithKeySetOptions) => Effect.Effect<Verified<S["Type"]> & { readonly key: PublicKey;}, JwtError, S["DecodingServices"] | Jwks | Signature.Signature>Decoding
decodeUnverified
unstableReads the protected header and claims of a signed JWT without verifying it.
Gotchas
Nothing returned here is authenticated. Use it only to choose how to verify, never to authorize.
See
Signature
declare const decodeUnverified: (...args: [token: string | Redacted<string>]) => Effect<Unverified, JoseError, never>Errors
Models
A decrypted and validated JWT, with its protected header and decryption key.
Signature
interface Decrypted<A> extends Verified<A, Jwe.ProtectedHeader> { readonly key: SecretKey<"dir">;}The registered claims of a JWT.
Signature
type RegisteredClaims = typeof RegisteredClaims.TypeThe protected header and claims of a signed JWT that has not been verified.
Signature
interface Unverified { readonly claims: Readonly<Record<string, Schema.Json>>; readonly protectedHeader: { [key: string]: Json; readonly alg: "RS256" | "RS384" | "RS512" | "PS256" | "PS384" | "PS512" | "ES256" | "ES384" | "ES512" | "EdDSA" | "HS256" | "HS384" | "HS512"; readonly cty?: string; readonly kid?: string; readonly typ?: string; };}A verified JWT: decoded application claims, its registered claims, and the authenticated protected header.
Signature
interface Verified<A, H = Jws.ProtectedHeader> { readonly claims: A; readonly protectedHeader: H; readonly registeredClaims: { readonly aud?: string | readonly Array<string>; readonly exp?: number; readonly iat?: number; readonly iss?: string; readonly jti?: string; readonly nbf?: number; readonly sub?: string; };}The claim validation policy for a signed or encrypted JWT.
Signature
interface VerifyOptions { readonly audience?: string | readonly Array<string>; readonly clockTolerance?: Input; readonly issuer?: string | readonly Array<string>; readonly maxTokenAge?: Input; readonly requiredClaims?: readonly Array<TypeOptionalKeys<{ readonly aud: optionalKey<Union<readonly [String, $Array<String>]>>; readonly exp: optionalKey<Finite>; readonly iat: optionalKey<Finite>; readonly iss: optionalKey<String>; readonly jti: optionalKey<String>; readonly nbf: optionalKey<Finite>; readonly sub: optionalKey<String>; }>>; readonly subject?: string; readonly typ?: string;}Options for verifyWithKeySet: the verification policy and the accepted algorithms.
Signature
interface VerifyWithKeySetOptions extends VerifyOptions, VerifyWithKeySetOptions {}Schemas
RegisteredClaims
unstableSchema for the registered claims: string iss, sub, and jti, a string
or string array aud, and finite NumericDate exp, nbf, and iat.
Signature
declare const RegisteredClaims: Struct<{ readonly aud: optionalKey<Union<readonly [String, $Array<String>]>>; readonly exp: optionalKey<Finite>; readonly iat: optionalKey<Finite>; readonly iss: optionalKey<String>; readonly jti: optionalKey<String>; readonly nbf: optionalKey<Finite>; readonly sub: optionalKey<String>;}>