Create and initialize the registry. Fetches JWKS from all providers on startup, loads disk cache as fallback, and spawns the periodic refresh task.
(config: JwtAuthConfig)
| 53 | /// Fetches JWKS from all providers on startup, loads disk cache as fallback, |
| 54 | /// and spawns the periodic refresh task. |
| 55 | pub async fn init(config: JwtAuthConfig) -> Self { |
| 56 | let cache = Arc::new(JwksCache::new(config.jwks_cache_path.clone())); |
| 57 | // Policy construction is infallible here because ServerConfig |
| 58 | // validation already ran at startup; fall back to strict on the |
| 59 | // unlikely internal error path so runtime never opens up. |
| 60 | let policy = Arc::new(config.jwks_policy().unwrap_or_default()); |
| 61 | |
| 62 | // Load disk cache first (offline fallback). |
| 63 | cache.load_from_disk(); |
| 64 | |
| 65 | // Fetch from all providers (best-effort — failures use disk cache). |
| 66 | for provider in &config.providers { |
| 67 | super::fetch::fetch_and_cache(&provider.name, &provider.jwks_url, &cache, &policy) |
| 68 | .await; |
| 69 | } |
| 70 | |
| 71 | // Spawn periodic refresh. |
| 72 | let refresh_handle = if !config.providers.is_empty() { |
| 73 | let pairs: Vec<(String, String)> = config |
| 74 | .providers |
| 75 | .iter() |
| 76 | .map(|p| (p.name.clone(), p.jwks_url.clone())) |
| 77 | .collect(); |
| 78 | Some(super::fetch::spawn_refresh_task( |
| 79 | pairs, |
| 80 | cache.clone(), |
| 81 | config.jwks_refresh_secs, |
| 82 | policy.clone(), |
| 83 | )) |
| 84 | } else { |
| 85 | None |
| 86 | }; |
| 87 | |
| 88 | Self { |
| 89 | providers: config.providers.clone(), |
| 90 | cache, |
| 91 | config, |
| 92 | policy, |
| 93 | _refresh_handle: refresh_handle, |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | /// Validate a JWT token using JWKS, routing by the `iss` claim. |
| 98 | /// |
no test coverage detected