Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,16 @@ redis = { version = "1.2", features = ["tokio-comp"], optional = true }
# features (see [features] below); `use_pem` is always required for PEM key
# parsing and is therefore enabled unconditionally.
jsonwebtoken = { version = "10", default-features = false, features = ["use_pem"] }
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json"] }
# reqwest 0.13's `rustls` feature hardwires the aws-lc-rs provider (C FFI, awkward
# for the musl static build). We keep the pure-Rust `ring` provider instead:
# `rustls-no-provider` builds rustls without a bundled provider, and auth/jwks.rs
# hands reqwest a fully preconfigured rustls ClientConfig (ring provider + bundled
# Mozilla roots from webpki-roots). Bundling the roots keeps the binary self-
# contained, so it works on musl / scratch / distroless images with no system CA
# bundle (matching reqwest 0.12's old `rustls-tls` behaviour).
reqwest = { version = "0.13", default-features = false, features = ["rustls-no-provider", "json"] }
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] }
Comment thread
coderabbitai[bot] marked this conversation as resolved.
webpki-roots = "1"
globset = "0.4"
base64 = "0.22"
sha2 = "0.11"
Expand Down
19 changes: 19 additions & 0 deletions src/auth/jwks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,30 @@ const MIN_REFRESH_INTERVAL: Duration = Duration::from_secs(60);
/// Bound the worst-case latency of a slow/stalled JWKS endpoint.
const JWKS_HTTP_TIMEOUT: Duration = Duration::from_secs(5);

/// Build the rustls client config for the JWKS HTTPS client.
///
/// Uses the pure-Rust `ring` provider (installed per-config, not process-global)
/// and bundles Mozilla's root store via `webpki-roots`, so the binary needs no
/// system CA bundle and works in musl / scratch / distroless images.
fn build_tls_config() -> rustls::ClientConfig {
let mut roots = rustls::RootCertStore::empty();
roots.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
rustls::ClientConfig::builder_with_provider(Arc::new(rustls::crypto::ring::default_provider()))
.with_safe_default_protocol_versions()
.expect("ring provider supports the default TLS protocol versions")
.with_root_certificates(roots)
.with_no_client_auth()
}

impl JwksCache {
/// Create a cache for `uri` (keys are loaded lazily on first lookup).
pub fn new(uri: String) -> Self {
let client = reqwest::Client::builder()
.timeout(JWKS_HTTP_TIMEOUT)
// Hand reqwest a fully preconfigured rustls backend rather than
// relying on a process-global default provider: no install ordering
// constraint, no global side effect, safe for library/test callers.
.tls_backend_preconfigured(build_tls_config())
.build()
.unwrap_or_default();
Self {
Expand Down