Expand description
§jwtiny - Minimal, Type-Safe JWT Validation
Minimal, type-safe JSON Web Token (JWT) validation for Rust.
jwtiny validates JWT tokens through a builder-pattern API that enforces correct validation
order at compile time. Born from the need for jsonwebtoken with miniserde support, it
evolved into a generic JWT library prioritizing safety, clarity, and zero-cost abstractions.
§Overview
JWTs (JSON Web Tokens) encode claims as JSON objects secured by digital signatures or message authentication codes. Validating them requires parsing Base64URL-encoded segments, verifying signatures with cryptographic keys, and checking temporal claims like expiration. Common pitfalls include algorithm confusion attacks (accepting asymmetric algorithms when only symmetric keys are trusted), server-side request forgery (SSRF) via untrusted issuer URLs, and timing vulnerabilities in signature comparison.
jwtiny addresses these through a type-safe state machine: parsing yields a ParsedToken,
issuer validation produces a TrustedToken, signature verification creates a VerifiedToken,
and claims validation returns the final Token. Each stage must complete before the next
begins, enforced by Rust’s type system. The builder pattern configures all steps upfront,
then executes them atomically—preventing partial validation and ensuring cryptographic keys
are only used after issuer checks complete.
§Quick Start
use jwtiny::*;
let token = TokenValidator::new(
ParsedToken::from_string(token_str)?
)
.ensure_issuer(|iss| Ok(iss == "https://trusted.com"))
.verify_signature(SignatureVerification::with_secret_hs256(b"secret"))
.validate_token(ValidationConfig::default())
.run()?;
println!("Subject: {:?}", token.subject());§Validation Flow
The library enforces a validation pipeline through type-level state transitions:
ParsedToken (parsed header and payload)
│ .ensure_issuer()
▼
TrustedToken (issuer validated; internal type)
│ .verify_signature()
▼
VerifiedToken (signature verified; internal type)
│ .validate_token()
▼
ValidatedToken (claims validated; internal type)
│ .run() / .run_async()
▼
Token (public API; safe to use)Only the final Token type is exposed publicly. Intermediate types (TrustedToken,
VerifiedToken, ValidatedToken) are internal, preventing partial validation from escaping
the builder.
§Algorithm Support
All algorithms implement a common Algorithm trait:
- HMAC (always enabled): HS256, HS384, HS512
- RSA (with
rsafeature): RS256, RS384, RS512 - ECDSA (with
ecdsafeature): ES256, ES384
§Signature Verification
Choose verification based on the algorithm family:
// Symmetric key (HMAC)
SignatureVerification::with_secret_hs256(b"your-256-bit-secret")
// Public key (RSA/ECDSA)
SignatureVerification::with_key(
Key::rsa_public(public_key_der),
AlgorithmPolicy::rs256_only(),
)
// Remote JWKS fetching
SignatureVerification::with_jwks(
http_client,
AlgorithmPolicy::recommended_asymmetric(),
true,
)Use algorithm-specific constructors (preferred) or pass an explicit
AlgorithmPolicy to prevent algorithm confusion.
§Claims Validation
Configure temporal and claim-specific checks:
ValidationConfig::default()
.require_audience("my-api") // Validate `aud` claim
.max_age(3600) // Token must be < 1 hour old
.clock_skew(60) // Allow 60s clock skew
.custom(|claims| { // Custom validation logic
if claims.subject.as_deref() != Some("admin") {
Err(Error::ClaimValidationFailed(
ClaimError::Custom("Admin only".to_string())
))
} else {
Ok(())
}
})§Features
- HMAC (always enabled): HS256, HS384, HS512
rsa: RSA algorithms (RS256, RS384, RS512)ecdsa: ECDSA algorithms (ES256, ES384)aws-lc-rs: Useaws-lc-rsbackend instead ofringfor RSA/ECDSAall-algorithms: Enable all asymmetric algorithms (RSA + ECDSA)remote: Remote JWKS over HTTPS (rustls). Provide an HTTP client.
§Security
§Algorithm Confusion Prevention
Always restrict algorithms explicitly. Without restrictions, a token declaring RS256 might be
accepted when you only intended to allow HS256.
§SSRF Prevention
When using JWKS, validate issuers before fetching keys. Without issuer validation, an attacker
can craft a token with an arbitrary iss claim, causing your application to fetch keys from
attacker-controlled URLs—a classic SSRF vulnerability.
§“none” Algorithm Rejection
The "none" algorithm (unsigned tokens) is always rejected per RFC 8725.
§Timing Attack Protection
HMAC signature verification uses constant-time comparison via the constant_time_eq
crate, preventing timing-based key recovery attacks.
§References
Re-exports§
pub use token::ParsedToken;pub use token::Token;pub use validator::TokenValidator;pub use claims::ValidationConfig;pub use validator::SignatureVerification;pub use algorithm::AlgorithmId;pub use algorithm::AlgorithmPolicy;pub use claims::Claims;pub use error::ClaimError;pub use error::Error;pub use error::Result;pub use keys::Key;pub use token::TokenHeader;