diff --git a/jwt-authorizer/src/oidc.rs b/jwt-authorizer/src/oidc.rs index 988d0b7..aea1674 100644 --- a/jwt-authorizer/src/oidc.rs +++ b/jwt-authorizer/src/oidc.rs @@ -1,3 +1,4 @@ +use reqwest::{Client, Url}; use serde::Deserialize; use crate::error::InitError; @@ -8,13 +9,20 @@ pub struct OidcDiscovery { pub jwks_uri: String, } +fn discovery_url(issuer: &str) -> Result { + let mut url = Url::parse(issuer).map_err(|e| InitError::DiscoveryError(e.to_string()))?; + + url.path_segments_mut() + .map_err(|_| InitError::DiscoveryError(format!("Issuer URL error! ('{issuer}' cannot be a base)")))? + .pop_if_empty() + .extend(&[".well-known", "openid-configuration"]); + + Ok(url) +} + pub async fn discover_jwks(issuer: &str) -> Result { - let discovery_url = reqwest::Url::parse(issuer) - .map_err(|e| InitError::DiscoveryError(e.to_string()))? - .join(".well-known/openid-configuration") - .map_err(|e| InitError::DiscoveryError(e.to_string()))?; - reqwest::Client::new() - .get(discovery_url) + Client::new() + .get(discovery_url(issuer)?) .send() .await .map_err(|e| InitError::DiscoveryError(e.to_string()))? @@ -23,3 +31,24 @@ pub async fn discover_jwks(issuer: &str) -> Result { .map_err(|e| InitError::DiscoveryError(e.to_string())) .map(|d| d.jwks_uri) } + +#[test] +fn discovery() { + assert_eq!( + Url::parse("http://host.com:99/xx/.well-known/openid-configuration").unwrap(), + discovery_url("http://host.com:99/xx").unwrap() + ); + assert_eq!( + Url::parse("http://host.com:99/xx/.well-known/openid-configuration").unwrap(), + discovery_url("http://host.com:99/xx/").unwrap() + ); + assert_eq!( + Url::parse("http://host.com:99/xx/yy/.well-known/openid-configuration").unwrap(), + discovery_url("http://host.com:99/xx/yy").unwrap() + ); + assert_eq!( + Url::parse("http://host.com:99/.well-known/openid-configuration").unwrap(), + discovery_url("http://host.com:99").unwrap() + ); + assert!(discovery_url("xxx").is_err()); +}