26 releases (6 breaking)

Uses new Rust 2024

0.7.0 May 7, 2026
0.6.4 Apr 28, 2026
0.6.1 Mar 30, 2026

#338 in Authentication

Download history 64/week @ 2026-01-22 24/week @ 2026-01-29 113/week @ 2026-02-05 66/week @ 2026-02-12 78/week @ 2026-02-19 39/week @ 2026-02-26 61/week @ 2026-03-05 93/week @ 2026-03-12 43/week @ 2026-03-19 16/week @ 2026-03-26 23/week @ 2026-04-02 83/week @ 2026-04-16 112/week @ 2026-04-23 138/week @ 2026-04-30 46/week @ 2026-05-07

379 downloads per month
Used in cf-oagw

Apache-2.0

625KB
11K SLoC

ModKit Auth

Authentication infrastructure for CyberFabric / ModKit.

Overview

The cf-modkit-auth crate provides:

  • JWT / JWKSKeyProvider trait, JwksKeyProvider with background key refresh, ValidationConfig, standard claim constants
  • Token validationTokenValidator trait, ClaimsError / AuthError error types
  • Auth configurationAuthConfig (issuers, audiences, leeway, JWKS endpoint)
  • Outbound OAuth2 client credentialsToken handle with proactive background refresh and on-demand invalidation, OAuthClientConfig, BearerAuthLayer (tower), BearerAuthAutoRefreshLayer (reactive refresh on 401, port of go-appkit's AuthBearerRoundTripper), HttpClientBuilderExt for modkit-http integration
  • Auth metricsAuthMetrics trait with LoggingMetrics and NoOpMetrics implementations

Outbound OAuth2 quick start

use modkit_auth::{HttpClientBuilderExt, OAuthClientConfig, SecretString, Token};
use modkit_http::HttpClientBuilder;

let token = Token::new(OAuthClientConfig {
    token_endpoint: Some("https://idp.example.com/oauth/token".parse()?),
    client_id: "my-service".into(),
    client_secret: SecretString::new("my-secret"),
    scopes: vec!["api.read".into()],
    ..Default::default()
})
.await?;

let client = HttpClientBuilder::new()
    .with_bearer_auth(token)
    .build()?;

// Every request gets Authorization: Bearer <token> automatically
let resp = client.get("https://api.example.com/resource").send().await?;

Reactive refresh on 401

with_bearer_auth covers the proactive case: the background TokenWatcher refreshes the credential before TTL expires. It does not detect tokens revoked out-of-band by the issuer — those surface only as a 401 from the upstream.

with_bearer_auth_auto_refresh adds the reactive half: on a 401 response it calls Token::invalidate(), re-reads the cached token, and replays the original request once with the refreshed credential. Behavior is a port of go-appkit's AuthBearerRoundTripper:

  • requests that already carry the configured auth header pass through untouched (no refresh, no retry);
  • Token::invalidate() is throttled per layer instance — default 15 minutes via modkit_auth::oauth2::DEFAULT_MIN_INVALIDATION_INTERVAL — so a burst of 401s will not hammer the token endpoint;
  • if the refreshed token equals the previous value, or if the invalidate fetch fails, the original 401 is surfaced as-is (no retry loop);
  • exactly one retry per call, no backoff. For multi-step retry strategies, compose with modkit_http::RetryLayer.
use modkit_auth::{
    BearerAuthAutoRefreshOpts, HttpClientBuilderExt, OAuthClientConfig, SecretString, Token,
};
use modkit_http::HttpClientBuilder;
use std::sync::Arc;
use std::time::Duration;

let token = Token::new(OAuthClientConfig { /**/ ..Default::default() }).await?;

// Defaults: Authorization header, retry on 401 only, 15-min throttle.
let client = HttpClientBuilder::new()
    .with_bearer_auth_auto_refresh(token.clone())
    .build()?;

// Custom predicate / header / throttle:
let opts = BearerAuthAutoRefreshOpts {
    min_invalidation_interval: Duration::from_secs(60),
    should_refresh: Arc::new(|s| s.as_u16() == 401 || s.as_u16() == 419),
    header_name: http::header::AUTHORIZATION,
};
let custom = HttpClientBuilder::new()
    .with_bearer_auth_auto_refresh_opts(token, opts)
    .build()?;

Cost: auto-refresh keeps a clone of the request body so it can be replayed on retry. With modkit-http's default body (Full<Bytes>) this is a reference-counted bump; with custom B, the type must be Clone. Pick the plain with_bearer_auth when the upstream is known not to revoke tokens out-of-band.

See examples/ for more patterns (OIDC discovery, token invalidation, shared token, form auth).

License

Licensed under Apache-2.0.

Dependencies

~110MB
~2.5M SLoC