authentication-verifier
Offline RS256 JWT verification for Main X Index peer services.
The authentication-service is
the federation's single sign-on provider: it signs RS256 access tokens
and publishes its RSA public keys at /.well-known/jwks.json. Every
other service verifies those tokens offline with this crate — fetch
the JWKS once at boot, build a Verifier, then verify each bearer
token locally. No shared secret, no per-request introspection hop.
- Spec: spec/index.md
- Agent guide: AGENTS.md
- Issuing service: authentication-service-rust-crate
Quick start
[]
= { = "../authentication/authentication-verifier-rust-crate" }
# or, to fetch the JWKS over HTTPS at boot:
# authentication-verifier = { path = "...", features = ["fetch"] }
use ;
// Boot: build from a JWKS document you already have…
let jwks: Value = from_str?;
let verifier = from_jwks_value?;
// …or fetch it over HTTPS (requires the `fetch` feature):
// let verifier = Verifier::from_jwks_url(
// "https://auth.example.gov/.well-known/jwks.json",
// "authentication-service",
// "main-x-service",
// ).await?;
// Per request: verify the bearer token locally.
let claims: Claims = verifier.verify?;
println!; // the user pid (UUID)
Construct the Verifier once and share it behind an Arc; verify
is read-only and allocation-light.
API summary
| Item | Purpose |
|---|---|
Verifier::from_jwks_value(&jwks, issuer, audience) |
Build from an in-memory JWKS document. Loads RSA keys only (non-RSA kty entries are skipped); an empty key set is permitted and rejects every token with UnknownKid. |
Verifier::from_jwks_url(url, issuer, audience).await |
Fetch the JWKS over HTTPS, then build. Requires features = ["fetch"] (pulls in reqwest with rustls). |
Verifier::verify(token) -> Result<Claims, VerifyError> |
Select the key by the token header kid, check the RS256 signature, then enforce iss, aud, and exp. |
Verifier::key_count() -> usize |
Number of RSA keys loaded from the JWKS. |
Claims |
Verified claims: sub (user pid, UUID string), email, name, iss, aud, exp, iat, jti (= the auth-service sessions.jid). |
VerifyError variants
| Variant | Meaning |
|---|---|
Jwks(String) |
The JWKS document was missing or structurally invalid (no keys array; RSA entry missing kid/n/e; bad modulus/exponent). |
MissingKid |
The token header carries no kid, so no key can be selected. |
UnknownKid(String) |
No loaded key matches the token's kid — stale JWKS cache, wrong issuer, or forgery. Refetch the JWKS to pick up a key rotation. |
Jwt(jsonwebtoken::errors::Error) |
Signature, issuer, audience, or expiry validation failed. |
Fetch(String) |
Fetching the JWKS over HTTP failed (only with the fetch feature). |
The JWKS / kid contract
This crate is the peer-side mirror of the auth-service's own token
verification: same RS256 algorithm, same Claims shape, same kid
selection — but keyed off the published JWKS rather than a locally
held key, so any service can embed it.
- The service publishes RSA signing keys as
{kty: "RSA", use: "sig", alg: "RS256", kid, n, e}withn/ebase64url (no padding). kid= base64url, no padding, ofSHA-256(big-endian RSA modulus bytes)— a stable thumbprint, stamped into every token header.Claimsis duplicated byte-identically between the service and this crate by convention; the service's cross-crate contract test pins the round-trip.- Default issuer/audience:
authentication-service/main-x-service(the service'sJWT_ISSUER/JWT_AUDIENCE). - Revocation (signout) is enforced only at the auth service. Peers
honour a token until
exp; the service keeps TTLs short (default 3600 s) to bound that window.
Testing
License
MIT OR Apache-2.0 OR GPL-2.0 OR GPL-3.0 OR BSD-3-Clause