Fork i18n + search + filtering- v0.2
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 94 lines 3.4 kB view raw
1use anyhow::Result; 2use axum::{ 3 extract::State, 4 http::{header, HeaderValue}, 5 response::{IntoResponse, Response}, 6}; 7use std::sync::Arc; 8 9use crate::http::{context::WebContext, errors::WebError}; 10use crate::jose::jwk::{WrappedJsonWebKey, WrappedJsonWebKeySet}; 11 12// Function to compute JWKS data and serialize to JSON string 13fn compute_jwks_json(web_context: &WebContext) -> Result<String, serde_json::Error> { 14 let mut keys = vec![]; 15 let signing_keys = web_context.config.signing_keys.as_ref(); 16 17 for available_signing_key in web_context.config.oauth_active_keys.as_ref() { 18 let available_signing_key = available_signing_key.clone(); 19 20 let signing_key = match signing_keys.get(&available_signing_key) { 21 Some(key) => key.clone(), 22 None => continue, 23 }; 24 let public_key = signing_key.public_key(); 25 26 let wrapped_json_web_key = WrappedJsonWebKey { 27 jwk: public_key.to_jwk(), 28 kid: Some(available_signing_key.clone()), 29 alg: Some("ES256".to_string()), 30 }; 31 32 keys.push(wrapped_json_web_key); 33 } 34 35 let jwks = WrappedJsonWebKeySet { keys }; 36 serde_json::to_string(&jwks) 37} 38 39// Global cache for the pre-serialized JSON string 40static JWKS_JSON_CACHE: once_cell::sync::OnceCell<Arc<String>> = once_cell::sync::OnceCell::new(); 41 42#[tracing::instrument(skip_all, err)] 43pub async fn handle_oauth_jwks( 44 State(web_context): State<WebContext>, 45) -> Result<impl IntoResponse, WebError> { 46 tracing::debug!("handle_oauth_jwks"); 47 48 // Initialize the cache if needed 49 if JWKS_JSON_CACHE.get().is_none() { 50 // Compute and serialize the JWKS data 51 let jwks_json = compute_jwks_json(&web_context) 52 .map_err(|e| anyhow::anyhow!("error-oauth-jwks-1 Failed to serialize JWKS: {}", e))?; 53 54 // Store in cache - don't worry if another thread beat us to it 55 let _ = JWKS_JSON_CACHE.set(Arc::new(jwks_json)); 56 } 57 58 // By this point, the cache should be initialized - either by us or another thread 59 // In the extremely unlikely event it's still not initialized, we'll create it one more time 60 let jwks_json = if let Some(json) = JWKS_JSON_CACHE.get() { 61 json 62 } else { 63 // Final attempt to compute and cache 64 let jwks_json = compute_jwks_json(&web_context) 65 .map_err(|e| anyhow::anyhow!("error-oauth-jwks-1 Failed to serialize JWKS: {}", e))?; 66 67 // Create a new Arc and set it in the cache 68 let json_arc = Arc::new(jwks_json); 69 70 // This will either succeed in setting it, or another thread beat us to it 71 if JWKS_JSON_CACHE.set(json_arc.clone()).is_err() { 72 // Another thread set it first, so use that value 73 JWKS_JSON_CACHE.get().ok_or_else(|| { 74 anyhow::anyhow!("error-oauth-jwks-2 Failed to initialize JWKS cache") 75 })? 76 } else { 77 // We set it, so we can use our local copy 78 JWKS_JSON_CACHE.get().ok_or_else(|| { 79 anyhow::anyhow!("error-oauth-jwks-2 Failed to initialize JWKS cache") 80 })? 81 } 82 }; 83 84 // Create response with proper content type 85 let mut response = Response::new((**jwks_json).clone()); 86 87 // Set content type to application/json 88 response.headers_mut().insert( 89 header::CONTENT_TYPE, 90 HeaderValue::from_static("application/json"), 91 ); 92 93 Ok(response) 94}