This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Build the project (standard Rust build)
cargo build --release
# Build for AWS Lambda deployment (requires cargo-lambda)
cargo lambda build --locked --release
# Run tests
cargo test
# Run a single test
cargo test <test_name>
# Run tests with output visible
cargo test -- --nocapture
# Format code
cargo fmt
# Check formatting without modifying
cargo fmt -- --check
# Run linter
cargo clippy -- -D warnings
# Generate code coverage (requires cargo-llvm-cov)
cargo llvm-cov --all-features --lcov --output-path lcov.info
# Run security audit (requires cargo-audit)
# RUSTSEC-2023-0071: rsa timing sidechannel — only affects decryption, not signature verification (safe to ignore)
# RUSTSEC-2024-0436: paste unmaintained — transitive dep of cel-interpreter, low risk
cargo audit --ignore RUSTSEC-2023-0071 --ignore RUSTSEC-2024-0436This is an AWS Lambda authorizer for API Gateway that validates OIDC-issued JWT tokens. Written in Rust for optimal cold start performance and low memory usage.
-
main.rs - Entry point. Reads environment variables, initializes the
KeysStorageandHandler, then starts the Lambda runtime. -
handler.rs - Implements the Lambda
Servicetrait. Thedo_callmethod orchestrates the validation:- Parses Bearer token from Authorization header
- Decodes JWT header to extract
kidandalg - Validates signing algorithm against accepted list
- Retrieves public key from JWKS endpoint
- Validates token (signature, expiration, issuer, audience)
- Evaluates CEL expression against token header and claims (if configured)
- Returns Allow/Deny policy document
-
keys_storage.rs - Async JWKS key cache with rate-limited refresh. Uses
RwLockfor concurrent access. Optionally pre-warms from a file on disk at startup. Fetches keys from OIDC provider's JWKS endpoint on cache miss and emits a structuredjwks_refresh_neededlog event when pre-warming was active. -
keysmap.rs - Wraps
HashMap<String, DecodingKey>for storing decoded public keys bykid. -
models.rs - API Gateway authorizer request/response types (
TokenAuthorizerEvent,TokenAuthorizerResponse).
- accepted_algorithms.rs - Validates JWT signing algorithms against configured allow-list
- accepted_claims.rs - Validates
issandaudclaims - cel_validation.rs - Evaluates CEL expressions for custom token validation
- principalid_claims.rs - Extracts principal ID from token claims
- parse_token_from_header.rs - Extracts Bearer token from Authorization header
- Static lifetime references (
Box::leak) for handler dependencies to satisfy Lambda runtime requirements - Optional JWKS cache pre-warming from a file on disk (e.g., Lambda layer) for faster cold starts
- Optimistic JWKS caching - keys refresh only on cache miss, rate-limited by
MIN_REFRESH_RATE - Allow policy uses wildcard resource (
*) to avoid cache conflicts across endpoints
JWKS_URI(required) - OIDC provider's JWKS endpoint URLACCEPTED_ISSUERS- Comma-separated list of validissvaluesACCEPTED_AUDIENCES- Comma-separated list of validaudvaluesACCEPTED_ALGORITHMS- Comma-separated list of valid signing algorithms (ES256, RS256, etc.)MIN_REFRESH_RATE- Seconds between JWKS refreshes (default: 900)JWKS_PRE_CACHED_FILE_PATH- Optional path to pre-cached JWKS file for pre-warming the cache at startup (e.g.,/opt/jwks.jsonfrom a Lambda layer). Emitsevent_type=jwks_refresh_neededlog when a cache miss triggers a network refresh.PRINCIPAL_ID_CLAIMS- Claims to use for principal ID (default: "preferred_username, sub")DEFAULT_PRINCIPAL_ID- Fallback principal ID (default: "unknown")TOKEN_VALIDATION_CEL- CEL expression for custom token validation (optional, see below)
The TOKEN_VALIDATION_CEL environment variable accepts a CEL (Common Expression Language) expression that is evaluated against the decoded JWT token's header and claims after signature verification.
header- JWT header fields (alg,kid,typ, etc.)claims- JWT payload claims (iss,sub,aud,email, custom claims, etc.)
- Boolean operators:
&&,||,! - Comparisons:
==,!=,<,>,<=,>= - Ternary:
condition ? true_value : false_value - Membership:
in(e.g.,"admin" in claims.roles) - String methods:
startsWith(),endsWith(),contains(),matches() - List macros:
exists(),all() - Presence check:
has()(e.g.,has(claims.email))
# Require non-empty subject and verified email
claims.sub != "" && claims.email_verified == true
# Validate JWT header type
header.typ == "JWT"
# Require admin role (array claim)
claims.roles.exists(r, r == "admin")
# Email domain allow-list
claims.email.endsWith("@example.com") || claims.email.endsWith("@example.org")
# Optional claim validation (only check if present)
!has(claims.acr) || claims.acr == "urn:mfa"
# Validate kid naming convention
header.kid.startsWith("prod-")
# Combined header and claims validation
claims.iss == "https://issuer.example.com" && header.kid.startsWith("issuer-")
- If
TOKEN_VALIDATION_CELis empty or unset, CEL validation is skipped - If the expression evaluates to
false, the request is denied - If CEL compilation fails at startup, the Lambda fails to initialize
- If CEL execution fails at runtime, the request is denied (fail closed)
These are SAM template parameters (not environment variables):
LambdaLayers- Comma-separated list of Lambda layer ARNs to attach (e.g., JWKS pre-cache layer, monitoring extensions)
Tests use httpmock to simulate JWKS endpoints. Test fixtures in tests/fixtures/keys/ contain key pairs for various algorithms (RS256, RS384, RS512, ES256, ES384, PS256, PS384, PS512, EdDSA). Pre-warming tests use tempfile for temporary JWKS files and tracing-test to verify structured log events.