diff --git a/src/auth.rs b/src/auth.rs index 0cf0f67..b2f8c8d 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -10,10 +10,17 @@ pub struct Claims { pub exp: usize, pub iat: usize, pub iss: String, - pub aud: String, + pub aud: Audience, } -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] +#[serde(untagged)] +pub enum Audience { + Single(String), + Multiple(Vec), +} + +#[derive(Debug, Deserialize, Clone)] struct Jwk { #[serde(rename = "kty")] _kty: String, @@ -31,13 +38,17 @@ struct Jwks { pub struct JwksVerifier { issuer: String, + audience: String, jwks_uri: String, keys: Arc>>, client: Client, } impl JwksVerifier { - pub async fn new(issuer: String) -> Result> { + pub async fn new( + issuer: String, + audience: String, + ) -> Result> { let client = Client::new(); // Authentik OIDC discovery let discovery_url = format!( @@ -53,6 +64,7 @@ impl JwksVerifier { let verifier = Self { issuer, + audience, jwks_uri, keys: Arc::new(RwLock::new(Vec::new())), client, @@ -73,18 +85,29 @@ impl JwksVerifier { let header = decode_header(token)?; let kid = header.kid.ok_or("Missing kid in token header")?; - let keys = self.keys.read().await; - let jwk = keys - .iter() - .find(|k| k.kid == kid) - .ok_or("Key not found in JWKS")?; + let jwk = { + let keys = self.keys.read().await; + keys.iter().find(|k| k.kid == kid).cloned() + }; + + let jwk = match jwk { + Some(key) => key, + None => { + self.refresh_keys().await?; + let keys = self.keys.read().await; + keys.iter() + .find(|k| k.kid == kid) + .cloned() + .ok_or("Key not found in JWKS")? + } + }; let decoding_key = DecodingKey::from_rsa_components(&jwk.n, &jwk.e)?; let mut validation = Validation::new(Algorithm::RS256); validation.set_issuer(&[self.issuer.clone()]); - // Aud validation might need careful config, usually it's the client_id - validation.validate_aud = false; + validation.set_audience(&[self.audience.clone()]); + validation.validate_aud = true; let token_data = decode::(token, &decoding_key, &validation)?; Ok(token_data.claims) diff --git a/src/server.rs b/src/server.rs index e7d53b5..4ccffd5 100644 --- a/src/server.rs +++ b/src/server.rs @@ -97,7 +97,10 @@ pub async fn start(db_url: &str) -> Result<(), Box> { let authentik_client_secret = std::env::var("AUTHENTIK_CLIENT_SECRET").map_err(|_| "AUTHENTIK_CLIENT_SECRET not set")?; - let verifier = Arc::new(crate::auth::JwksVerifier::new(authentik_issuer.clone()).await?); + let verifier = Arc::new( + crate::auth::JwksVerifier::new(authentik_issuer.clone(), authentik_client_id.clone()) + .await?, + ); let authenticator = Arc::new( crate::auth::Authenticator::new( authentik_issuer,