#[cfg(test)]
mod tests {
use crate::common::error::JwtError;
use crate::oidc::discovery::{DiscoveryDocument, OidcDiscovery};
use mockito::Server;
use reqwest::Client;
use std::time::Duration;
#[tokio::test]
async fn test_discover_with_fallback_success() {
let mut server = Server::new_async().await;
let mock_server = server.mock("GET", "/.well-known/openid-configuration")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(
format!(r#"{{
"issuer": "{}",
"jwks_uri": "{}/.well-known/jwks.json",
"authorization_endpoint": "{}/oauth2/authorize",
"token_endpoint": "{}/oauth2/token"
}}"#, server.url(), server.url(), server.url(), server.url()),
)
.create();
let discovery = OidcDiscovery::new(Duration::from_secs(3600));
let document = discovery
.discover_with_fallback(&server.url(), Some("http://fallback-url/jwks.json"))
.await
.unwrap();
assert_eq!(document.issuer, server.url());
assert_eq!(
document.jwks_uri,
format!("{}/.well-known/jwks.json", server.url())
);
mock_server.assert();
}
#[tokio::test]
async fn test_discover_with_fallback_failure() {
let mut server = Server::new_async().await;
let mock_server = server.mock("GET", "/.well-known/openid-configuration")
.with_status(404)
.create();
let discovery = OidcDiscovery::new(Duration::from_secs(3600));
let document = discovery
.discover_with_fallback(&server.url(), Some("http://fallback-url/jwks.json"))
.await
.unwrap();
assert_eq!(document.issuer, server.url());
assert_eq!(document.jwks_uri, "http://fallback-url/jwks.json");
mock_server.assert();
}
#[tokio::test]
async fn test_discover_with_fallback_no_fallback() {
let mut server = Server::new_async().await;
let mock_server = server.mock("GET", "/.well-known/openid-configuration")
.with_status(404)
.create();
let discovery = OidcDiscovery::new(Duration::from_secs(3600));
let result = discovery.discover_with_fallback(&server.url(), None).await;
assert!(result.is_err());
mock_server.assert();
}
#[test]
fn test_discovery_document_new() {
let document = DiscoveryDocument::new("https://example.com", "https://example.com/jwks.json");
assert_eq!(document.issuer, "https://example.com");
assert_eq!(document.jwks_uri, "https://example.com/jwks.json");
assert_eq!(document.authorization_endpoint, None);
assert_eq!(document.token_endpoint, None);
assert_eq!(document.userinfo_endpoint, None);
}
#[test]
fn test_discovery_document_with_endpoints() {
let document = DiscoveryDocument::with_endpoints(
"https://example.com",
"https://example.com/jwks.json",
Some("https://example.com/auth"),
Some("https://example.com/token"),
Some("https://example.com/userinfo"),
);
assert_eq!(document.issuer, "https://example.com");
assert_eq!(document.jwks_uri, "https://example.com/jwks.json");
assert_eq!(document.authorization_endpoint, Some("https://example.com/auth".to_string()));
assert_eq!(document.token_endpoint, Some("https://example.com/token".to_string()));
assert_eq!(document.userinfo_endpoint, Some("https://example.com/userinfo".to_string()));
}
#[test]
fn test_discovery_document_validate_success() {
let document = DiscoveryDocument::new("https://example.com", "https://example.com/jwks.json");
let result = document.validate("https://example.com");
assert!(result.is_ok());
}
#[test]
fn test_discovery_document_validate_issuer_mismatch() {
let document = DiscoveryDocument::new("https://example.com", "https://example.com/jwks.json");
let result = document.validate("https://wrong-issuer.com");
assert!(result.is_err());
match result.unwrap_err() {
JwtError::ConfigurationError { parameter, error } => {
assert_eq!(parameter, Some("issuer".to_string()));
assert!(error.contains("Issuer mismatch"));
}
_ => panic!("Expected ConfigurationError"),
}
}
#[test]
fn test_discovery_document_validate_empty_jwks_uri() {
let mut document = DiscoveryDocument::new("https://example.com", "https://example.com/jwks.json");
document.jwks_uri = "".to_string();
let result = document.validate("https://example.com");
assert!(result.is_err());
match result.unwrap_err() {
JwtError::ConfigurationError { parameter, error } => {
assert_eq!(parameter, Some("jwks_uri".to_string()));
assert!(error.contains("JWKS URI is empty"));
}
_ => panic!("Expected ConfigurationError"),
}
}
#[test]
fn test_discovery_document_validate_invalid_jwks_uri() {
let mut document = DiscoveryDocument::new("https://example.com", "https://example.com/jwks.json");
document.jwks_uri = "invalid-url".to_string();
let result = document.validate("https://example.com");
assert!(result.is_err());
match result.unwrap_err() {
JwtError::ConfigurationError { parameter, error } => {
assert_eq!(parameter, Some("jwks_uri".to_string()));
assert!(error.contains("JWKS URI must start with http:// or https://"));
}
_ => panic!("Expected ConfigurationError"),
}
}
#[test]
fn test_cache_operations() {
let discovery = OidcDiscovery::new(Duration::from_secs(3600));
let document = DiscoveryDocument::new("https://example.com", "https://example.com/jwks.json");
discovery.add_to_cache("https://example.com", document.clone());
assert!(discovery.is_cached("https://example.com"));
assert!(!discovery.is_cached("https://other.com"));
let issuers = discovery.get_cached_issuers();
assert_eq!(issuers.len(), 1);
assert_eq!(issuers[0], "https://example.com");
discovery.clear_cache("https://example.com");
assert!(!discovery.is_cached("https://example.com"));
discovery.add_to_cache("https://example.com", document);
discovery.add_to_cache("https://other.com", DiscoveryDocument::new("https://other.com", "https://other.com/jwks.json"));
assert_eq!(discovery.get_cached_issuers().len(), 2);
discovery.clear_all_cache();
assert_eq!(discovery.get_cached_issuers().len(), 0);
}
#[test]
fn test_cache_duration() {
let mut discovery = OidcDiscovery::new(Duration::from_secs(3600));
assert_eq!(discovery.get_cache_duration(), Duration::from_secs(3600));
discovery.set_cache_duration(Duration::from_secs(7200));
assert_eq!(discovery.get_cache_duration(), Duration::from_secs(7200));
}
#[test]
fn test_with_client() {
let client = Client::builder()
.timeout(Duration::from_secs(10))
.build()
.unwrap();
let discovery = OidcDiscovery::with_client(client, Duration::from_secs(3600));
assert_eq!(discovery.get_cache_duration(), Duration::from_secs(3600));
}
}