stormchaser_api/auth/
jwks.rs1use std::collections::HashMap;
2
3#[derive(Clone)]
5pub struct OidcConfig {
6 pub issuer: String,
8 pub external_issuer: String,
10 pub client_id: String,
12 pub client_secret: String,
14 pub jwks_url: String,
16}
17
18pub type JwksCache = HashMap<String, jsonwebtoken::jwk::Jwk>;
20
21pub 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}