#[cfg(test)]
mod tests {
use crate::common::error::JwtError;
use crate::jwk::provider::JwkProvider;
use mockito::Server;
use std::time::Duration;
#[tokio::test]
async fn test_jwk_provider_new_valid_params() {
let provider =
JwkProvider::new("us-east-1", "us-east-1_example", Duration::from_secs(3600));
assert!(provider.is_ok());
let provider = provider.unwrap();
assert_eq!(
provider.get_issuer(),
"https://cognito-idp.us-east-1.amazonaws.com/us-east-1_example"
);
}
#[tokio::test]
async fn test_jwk_provider_new_empty_region() {
let provider = JwkProvider::new("", "us-east-1_example", Duration::from_secs(3600));
assert!(provider.is_err());
if let Err(JwtError::ConfigurationError {
parameter,
error: _,
}) = provider
{
assert_eq!(parameter, Some("region".to_string()));
} else {
panic!("Expected ConfigurationError with parameter 'region'");
}
}
#[tokio::test]
async fn test_jwk_provider_new_empty_user_pool_id() {
let provider = JwkProvider::new("us-east-1", "", Duration::from_secs(3600));
assert!(provider.is_err());
if let Err(JwtError::ConfigurationError {
parameter,
error: _,
}) = provider
{
assert_eq!(parameter, Some("user_pool_id".to_string()));
} else {
panic!("Expected ConfigurationError with parameter 'user_pool_id'");
}
}
#[tokio::test]
async fn test_jwk_provider_new_invalid_user_pool_id() {
let provider = JwkProvider::new("us-east-1", "invalid-format", Duration::from_secs(3600));
assert!(provider.is_err());
if let Err(JwtError::ConfigurationError {
parameter,
error: _,
}) = provider
{
assert_eq!(parameter, Some("user_pool_id".to_string()));
} else {
panic!("Expected ConfigurationError with parameter 'user_pool_id'");
}
}
#[tokio::test]
async fn test_jwk_provider_fetch_success() {
let mut server = Server::new_async().await;
let mock_server = server.mock("GET", "/.well-known/jwks.json")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(r#"{
"keys": [
{
"kid": "test-key-1",
"alg": "RS256",
"use": "sig",
"n": "xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHLUXpq15Jw5E4oaxt_yiMiLaDs2KwUDzRda5idsOmMTllD05HG7YAV5EB7mXNX6yfQxRVm1ThE0wLi32XR-8dzUQsYATpspAGXql5iOPxW8bFQwQ",
"e": "AQAB"
},
{
"kid": "test-key-2",
"alg": "RS256",
"use": "sig",
"n": "vQJaJITRIP2TOYZLfIX8UQHl5XF-o2MQHJyVpX0hDSiIzUDQEQJd1hkjOYbEL1Y7HFPJiIZPI5ZL-vHR6L6HJ6HKKLMoSZ9i43MDgJ1j-9Bx5YID3kFtGi9aeW4gL9ZEUy-5OLTmOm8P-f3JeCKYwZWCw3JnLc0-9iLfRfMj6eDyPOUCF7g5rnTYH9PL9h6L1QkXMhCkG_dqggf_NHlmHHU7AkWUUyImeCes0TP7GyPL4_eXec3ZBf0jUtMOQAIy4PhRfLMPCmcTpLqBBPJmBW4WcHzMd4L_1ao8TZEjXQNjyNYKPBre1YeAEGhjK5_iw_hGqcUgnsSsGPzxHw",
"e": "AQAB"
}
]
}"#)
.create();
let provider =
JwkProvider::new_with_base_url(&server.url(), "test-issuer", Duration::from_secs(3600))
.expect("Failed to create JwkProvider");
let result = provider.prefetch_keys().await;
assert!(result.is_ok());
let key = provider.get_key("test-key-1").await;
assert!(key.is_ok());
let key = provider.get_key("test-key-2").await;
assert!(key.is_ok());
let key = provider.get_key("non-existent").await;
assert!(key.is_err());
if let Err(JwtError::KeyNotFound(kid)) = key {
assert_eq!(kid, "non-existent");
} else {
panic!("Expected KeyNotFound error");
}
mock_server.assert();
}
#[tokio::test]
async fn test_jwk_provider_fetch_error() {
let mut server = Server::new_async().await;
let mock_server = server
.mock("GET", "/.well-known/jwks.json")
.with_status(500)
.with_body("Internal Server Error")
.expect(3) .create();
let provider =
JwkProvider::new_with_base_url(&server.url(), "test-issuer", Duration::from_secs(3600))
.expect("Failed to create JwkProvider");
let result = provider.prefetch_keys().await;
assert!(result.is_err());
if let Err(JwtError::JwksFetchError { url: _, error: _ }) = result {
} else {
panic!("Expected JwksFetchError");
}
mock_server.assert();
}
#[tokio::test]
async fn test_jwk_provider_fetch_invalid_json() {
let mut server = Server::new_async().await;
let mock_server = server
.mock("GET", "/.well-known/jwks.json")
.with_status(200)
.with_header("content-type", "application/json")
.with_body("invalid json")
.create();
let provider =
JwkProvider::new_with_base_url(&server.url(), "test-issuer", Duration::from_secs(3600))
.expect("Failed to create JwkProvider");
let result = provider.prefetch_keys().await;
assert!(result.is_err());
if let Err(JwtError::ParseError { part: _, error: _ }) = result {
} else {
panic!("Expected ParseError");
}
mock_server.assert();
}
#[tokio::test]
async fn test_jwk_provider_fetch_empty_keys() {
let mut server = Server::new_async().await;
let mock_server = server
.mock("GET", "/.well-known/jwks.json")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(r#"{"keys": []}"#)
.expect(3) .create();
let provider =
JwkProvider::new_with_base_url(&server.url(), "test-issuer", Duration::from_secs(3600))
.expect("Failed to create JwkProvider");
let result = provider.prefetch_keys().await;
assert!(result.is_err());
if let Err(JwtError::JwksFetchError { url: _, error }) = &result {
assert!(error.contains("empty"));
} else {
panic!("Expected JwksFetchError with empty keys message");
}
mock_server.assert();
}
#[tokio::test]
async fn test_jwk_provider_cache_expiration() {
let mut server = Server::new_async().await;
let mock_server = server.mock("GET", "/.well-known/jwks.json")
.with_status(200)
.with_header("content-type", "application/json")
.with_body(r#"{
"keys": [
{
"kid": "test-key-1",
"alg": "RS256",
"use": "sig",
"n": "xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHLUXpq15Jw5E4oaxt_yiMiLaDs2KwUDzRda5idsOmMTllD05HG7YAV5EB7mXNX6yfQxRVm1ThE0wLi32XR-8dzUQsYATpspAGXql5iOPxW8bFQwQ",
"e": "AQAB"
}
]
}"#)
.expect(2) .create();
let provider = JwkProvider::new_with_base_url_and_refresh_interval(
&server.url(),
"test-issuer",
Duration::from_millis(100), Duration::from_secs(1),
)
.expect("Failed to create JwkProvider");
let result = provider.prefetch_keys().await;
assert!(result.is_ok());
let key1 = provider.get_key("test-key-1").await;
assert!(key1.is_ok());
tokio::time::sleep(Duration::from_millis(1200)).await;
let key2 = provider.get_key("test-key-1").await;
assert!(key2.is_ok());
assert!(key1.is_ok() && key2.is_ok());
mock_server.assert();
}
}