Skip to main content

stormchaser_api/auth/
jwks.rs

1use std::collections::HashMap;
2
3/// Configuration for OIDC authentication
4#[derive(Clone)]
5pub struct OidcConfig {
6    /// OIDC issuer URL
7    pub issuer: String,
8    /// External issuer URL
9    pub external_issuer: String,
10    /// OIDC client ID
11    pub client_id: String,
12    /// OIDC client secret
13    pub client_secret: String,
14    /// URL to fetch JWKS
15    pub jwks_url: String,
16}
17
18/// Type alias for JWKS cache
19pub type JwksCache = HashMap<String, jsonwebtoken::jwk::Jwk>;
20
21/// Fetches JSON Web Key Set (JWKS) from a specified URL
22pub async fn fetch_jwks(jwks_url: &str) -> JwksCache {
23    let mut jwks = HashMap::new();
24    let retry_policy =
25        reqwest_retry::policies::ExponentialBackoff::builder().build_with_max_retries(3);
26    let client = reqwest_middleware::ClientBuilder::new(reqwest::Client::new())
27        .with(reqwest_retry::RetryTransientMiddleware::new_with_policy(
28            retry_policy,
29        ))
30        .build();
31
32    match client.get(jwks_url).send().await {
33        Ok(resp) => {
34            if let Ok(jwks_set) = resp.json::<jsonwebtoken::jwk::JwkSet>().await {
35                for jwk in jwks_set.keys {
36                    if let Some(kid) = &jwk.common.key_id {
37                        jwks.insert(kid.clone(), jwk);
38                    }
39                }
40                tracing::info!("Successfully fetched {} keys from JWKS", jwks.len());
41            } else {
42                tracing::error!("Failed to parse JWKS response from {}", jwks_url);
43            }
44        }
45        Err(e) => {
46            tracing::error!("Failed to fetch JWKS from {}: {:?}", jwks_url, e);
47        }
48    }
49    jwks
50}