From 7a5d7ee03b12234fc8a9c3e17cf04f877637b0ae Mon Sep 17 00:00:00 2001 From: Andre Julius Date: Mon, 6 Nov 2023 16:31:45 +0100 Subject: [PATCH] Add support for custom http client in jwks discovery --- jwt-authorizer/src/authorizer.rs | 17 +++++++++++++-- jwt-authorizer/src/builder.rs | 36 ++++++++++++++++++++++++++++++-- jwt-authorizer/src/oidc.rs | 6 ++++-- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/jwt-authorizer/src/authorizer.rs b/jwt-authorizer/src/authorizer.rs index 0b3248b..c4c8a3f 100644 --- a/jwt-authorizer/src/authorizer.rs +++ b/jwt-authorizer/src/authorizer.rs @@ -3,7 +3,7 @@ use std::{io::Read, sync::Arc}; use headers::{authorization::Bearer, Authorization, HeaderMapExt}; use http::HeaderMap; use jsonwebtoken::{decode, decode_header, jwk::JwkSet, Algorithm, DecodingKey, TokenData}; -use reqwest::Url; +use reqwest::{Client, Url}; use serde::de::DeserializeOwned; use crate::{ @@ -56,6 +56,7 @@ where refresh: Option, validation: crate::validation::Validation, jwt_source: JwtSource, + http_client: Option, ) -> Result, InitError> { Ok(match key_source_type { KeySourceType::RSA(path) => { @@ -195,7 +196,7 @@ where } } KeySourceType::Discovery(issuer_url) => { - let jwks_url = Url::parse(&oidc::discover_jwks(issuer_url.as_str()).await?) + let jwks_url = Url::parse(&oidc::discover_jwks(issuer_url.as_str(), http_client).await?) .map_err(|e| InitError::JwksUrlError(e.to_string()))?; let key_store_manager = KeyStoreManager::new(jwks_url, refresh.unwrap_or_default()); @@ -318,6 +319,7 @@ mod tests { None, Validation::new(), JwtSource::AuthorizationHeader, + None, ) .await .unwrap(); @@ -343,6 +345,7 @@ mod tests { None, Validation::new(), JwtSource::AuthorizationHeader, + None, ) .await .unwrap(); @@ -358,6 +361,7 @@ mod tests { None, Validation::new(), JwtSource::AuthorizationHeader, + None, ) .await .unwrap(); @@ -370,6 +374,7 @@ mod tests { None, Validation::new(), JwtSource::AuthorizationHeader, + None, ) .await .unwrap(); @@ -382,6 +387,7 @@ mod tests { None, Validation::new(), JwtSource::AuthorizationHeader, + None, ) .await .unwrap(); @@ -394,6 +400,7 @@ mod tests { None, Validation::new(), JwtSource::AuthorizationHeader, + None, ) .await .unwrap(); @@ -419,6 +426,7 @@ mod tests { None, Validation::new(), JwtSource::AuthorizationHeader, + None, ) .await .unwrap(); @@ -431,6 +439,7 @@ mod tests { None, Validation::new(), JwtSource::AuthorizationHeader, + None, ) .await .unwrap(); @@ -443,6 +452,7 @@ mod tests { None, Validation::new(), JwtSource::AuthorizationHeader, + None, ) .await .unwrap(); @@ -458,6 +468,7 @@ mod tests { None, Validation::new(), JwtSource::AuthorizationHeader, + None, ) .await; println!("{:?}", a.as_ref().err()); @@ -472,6 +483,7 @@ mod tests { None, Validation::default(), JwtSource::AuthorizationHeader, + None, ) .await; println!("{:?}", a.as_ref().err()); @@ -486,6 +498,7 @@ mod tests { None, Validation::default(), JwtSource::AuthorizationHeader, + None, ) .await; println!("{:?}", a.as_ref().err()); diff --git a/jwt-authorizer/src/builder.rs b/jwt-authorizer/src/builder.rs index 46dece9..3245456 100644 --- a/jwt-authorizer/src/builder.rs +++ b/jwt-authorizer/src/builder.rs @@ -9,6 +9,8 @@ use crate::{ Authorizer, Refresh, RefreshStrategy, RegisteredClaims, Validation, }; +use reqwest::Client; + /// Authorizer Layer builder /// /// - initialisation of the Authorizer from jwks, rsa, ed, ec or secret @@ -22,6 +24,7 @@ where claims_checker: Option>, validation: Option, jwt_source: JwtSource, + http_client: Option, } /// alias for AuthorizerBuidler (backwards compatibility) @@ -40,6 +43,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -51,6 +55,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -61,6 +66,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -71,6 +77,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -82,6 +89,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -93,6 +101,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -104,6 +113,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -115,6 +125,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -126,6 +137,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -137,6 +149,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -148,6 +161,7 @@ where claims_checker: None, validation: None, jwt_source: JwtSource::AuthorizationHeader, + http_client: None, } } @@ -198,12 +212,30 @@ where self } + /// provide a custom http client for oicd requests + /// if not called, uses a default configured client + /// + /// (default: None) + pub fn http_client(mut self, http_client: Client) -> AuthorizerBuilder { + self.http_client = Some(http_client); + + self + } + /// Build axum layer #[deprecated(since = "0.10.0", note = "please use `IntoLayer::into_layer()` instead")] pub async fn layer(self) -> Result, InitError> { let val = self.validation.unwrap_or_default(); let auth = Arc::new( - Authorizer::build(self.key_source_type, self.claims_checker, self.refresh, val, self.jwt_source).await?, + Authorizer::build( + self.key_source_type, + self.claims_checker, + self.refresh, + val, + self.jwt_source, + None, + ) + .await?, ); Ok(AuthorizationLayer::new(vec![auth])) } @@ -211,6 +243,6 @@ where pub async fn build(self) -> Result, InitError> { let val = self.validation.unwrap_or_default(); - Authorizer::build(self.key_source_type, self.claims_checker, self.refresh, val, self.jwt_source).await + Authorizer::build(self.key_source_type, self.claims_checker, self.refresh, val, self.jwt_source, self.http_client).await } } diff --git a/jwt-authorizer/src/oidc.rs b/jwt-authorizer/src/oidc.rs index aea1674..567bdd2 100644 --- a/jwt-authorizer/src/oidc.rs +++ b/jwt-authorizer/src/oidc.rs @@ -20,8 +20,10 @@ fn discovery_url(issuer: &str) -> Result { Ok(url) } -pub async fn discover_jwks(issuer: &str) -> Result { - Client::new() +pub async fn discover_jwks(issuer: &str, client: Option) -> Result { + let client = client.unwrap_or_default(); + + client .get(discovery_url(issuer)?) .send() .await