Authentication
JWT, Basic, Bearer, and API-key authentication middleware for Tako routes.
Authentication
Tako ships four authentication middleware in tako-rs-plugins, re-exported
under tako::middleware::*. Each is a builder; configure it, then call
.into_middleware() and attach it globally or per-route. All four return
401 Unauthorized with the appropriate WWW-Authenticate challenge when
credentials are missing or invalid, and the static-credential paths use
constant-time comparison to avoid timing leaks.
This page covers the middleware that guards a route. To read already-parsed
credentials inside a handler (for example JwtClaimsVerified<T> produced by
JwtAuth), see the auth extractors.
Basic auth
RFC 7617 HTTP Basic. Configure a single user, multiple users, or a custom
verify closure that returns bool.
use tako::middleware::IntoMiddleware;
use tako::middleware::basic_auth::BasicAuth;
// Single static user.
let single = BasicAuth::single("admin", "pw")
.realm("Admin Area")
.into_middleware();
// Multiple static users.
let multi = BasicAuth::multiple([
("alice", "secret1"),
("bob", "secret2"),
]).into_middleware();
// Dynamic verification — returns bool, not a user object.
let dynamic = BasicAuth::with_verify(|user, pass| {
user == "admin" && pass == "pw"
}).into_middleware();realm(...) sets the WWW-Authenticate realm (default "Restricted").
users_with_verify(...) combines a static map with a fallback closure.
Bearer auth
RFC 6750 bearer tokens from the Authorization header. The scheme name is
matched case-insensitively.
use tako::middleware::IntoMiddleware;
use tako::middleware::bearer_auth::BearerAuth;
// Single static token.
let single = BearerAuth::static_token("my-secret-token").into_middleware();
// Multiple valid tokens.
let multi = BearerAuth::static_tokens([
"development-key",
"staging-key",
]).into_middleware();
// Dynamic verification.
let dynamic = BearerAuth::with_verify(|token| {
token.starts_with("user_")
}).into_middleware();static_tokens_with_verify(...) combines static tokens with a fallback
closure. For decoding claims out of a JWT bearer token, reach for JwtAuth
below instead — BearerAuth only answers yes/no.
API-key auth
Validate an API key drawn from a header (default X-API-Key), a query
parameter, or either.
use tako::middleware::IntoMiddleware;
use tako::middleware::api_key_auth::{ApiKeyAuth, ApiKeyLocation};
// Single key from the default X-API-Key header.
let basic = ApiKeyAuth::new("secret-api-key").into_middleware();
// Multiple keys from a custom header.
let multi = ApiKeyAuth::from_keys(["key1", "key2"])
.header_name("X-Custom-Key")
.into_middleware();
// From a query parameter.
let query = ApiKeyAuth::new("secret")
.location(ApiKeyLocation::Query("api_key"))
.into_middleware();
// Dynamic verification.
let dynamic = ApiKeyAuth::with_verify(|key| {
key.len() == 32 && key.chars().all(|c| c.is_ascii_hexdigit())
}).into_middleware();ApiKeyLocation is Header(name), Query(name), or
HeaderOrQuery(header, query) (header tried first). header_name(...) and
query_param(...) are shorthands.
JWT auth
JwtAuth<V> is trait-based: implement JwtVerifier with your preferred JWT
library, or enable the jwt-simple cargo feature for the bundled
MultiKeyVerifier (HMAC, RSA, RSA-PSS, ECDSA, EdDSA, BLAKE2b). On success the
decoded claims are inserted into the request extensions, where a handler can
read them.
use tako::middleware::IntoMiddleware;
use tako::middleware::jwt_auth::{JwtAuth, VerifyConstraints};
// `verifier` implements JwtVerifier (e.g. the jwt-simple MultiKeyVerifier).
let jwt = JwtAuth::new(verifier)
.constraints(VerifyConstraints {
issuer: Some("https://issuer.example".into()),
audience: Some("my-api".into()),
leeway_secs: 30,
})
.into_middleware();Capabilities:
- JWKS rotation — the
jwt-simpleMultiKeyVerifierselects keys bykidand exposesrotate_key/revoke_kidfor runtime rotation without a restart. - Constraints —
VerifyConstraintsenforcesiss,aud, and a clockleeway_secsuniformly across algorithms. The default verifier fails closed if constraints are set but the verifier cannot enforce them. - Revocation —
.revocation(list, extractor)checks aRevocationList(the bundledInMemoryRevocationListis keyed byjti) after signature verification. - Introspection —
.introspect(closure)runs an async callback on every request, the correct hook for opaque tokens or tenant-scoped revocation.
A VerifyConstraints set on JwtAuth only takes effect if the verifier
enforces it. The default validate_constraints rejects (returns 401) when
any non-default constraint is configured on a verifier that does not override
it — this prevents silently dropping iss / aud / leeway.
Where to register
Attach an auth middleware per-route to guard only the protected paths, or globally if the whole router is behind auth:
use tako::Method;
router
.route(Method::GET, "/admin", admin_only)
.middleware(BasicAuth::single("admin", "pw").into_middleware());See the middleware model for chain ordering, and the
runnable examples/auth
for a full Basic + Bearer setup.