1use crate::validation::ValidationConfig;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct AuthConfig {
7 #[serde(default = "default_leeway")]
9 pub leeway_seconds: i64,
10
11 #[serde(default)]
13 pub issuers: Vec<String>,
14
15 #[serde(default)]
17 pub audiences: Vec<String>,
18
19 #[serde(default = "default_require_exp")]
22 pub require_exp: bool,
23
24 #[serde(default)]
26 pub jwks: Option<JwksConfig>,
27}
28
29fn default_leeway() -> i64 {
30 60
31}
32
33fn default_require_exp() -> bool {
34 true
35}
36
37impl Default for AuthConfig {
38 fn default() -> Self {
39 Self {
40 leeway_seconds: default_leeway(),
41 issuers: Vec::new(),
42 audiences: Vec::new(),
43 require_exp: default_require_exp(),
44 jwks: None,
45 }
46 }
47}
48
49impl From<&AuthConfig> for ValidationConfig {
50 fn from(config: &AuthConfig) -> Self {
51 Self {
52 allowed_issuers: config.issuers.clone(),
53 allowed_audiences: config.audiences.clone(),
54 leeway_seconds: config.leeway_seconds,
55 require_exp: config.require_exp,
56 }
57 }
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct JwksConfig {
63 pub uri: String,
65
66 #[serde(default = "default_refresh_interval")]
68 pub refresh_interval_seconds: u64,
69
70 #[serde(default = "default_max_backoff")]
72 pub max_backoff_seconds: u64,
73}
74
75fn default_refresh_interval() -> u64 {
76 300
77}
78
79fn default_max_backoff() -> u64 {
80 3600
81}
82
83#[cfg(test)]
84#[cfg_attr(coverage_nightly, coverage(off))]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_default_config() {
90 let config = AuthConfig::default();
91 assert_eq!(config.leeway_seconds, 60);
92 assert!(config.issuers.is_empty());
93 assert!(config.audiences.is_empty());
94 assert!(config.require_exp);
95 assert!(config.jwks.is_none());
96 }
97
98 #[test]
99 fn test_auth_config_serialization() {
100 let config = AuthConfig {
101 leeway_seconds: 120,
102 issuers: vec!["https://auth.example.com".to_owned()],
103 audiences: vec!["api".to_owned()],
104 require_exp: true,
105 jwks: Some(JwksConfig {
106 uri: "https://auth.example.com/.well-known/jwks.json".to_owned(),
107 refresh_interval_seconds: 300,
108 max_backoff_seconds: 3600,
109 }),
110 };
111
112 let json = serde_json::to_string_pretty(&config).unwrap();
113 let deserialized: AuthConfig = serde_json::from_str(&json).unwrap();
114 assert_eq!(deserialized.leeway_seconds, 120);
115 assert_eq!(deserialized.issuers, vec!["https://auth.example.com"]);
116 assert_eq!(deserialized.audiences, vec!["api"]);
117 assert!(deserialized.require_exp);
118 let jwks = deserialized.jwks.expect("jwks should be present");
119 assert_eq!(jwks.uri, "https://auth.example.com/.well-known/jwks.json");
120 assert_eq!(jwks.refresh_interval_seconds, 300);
121 assert_eq!(jwks.max_backoff_seconds, 3600);
122 }
123
124 #[test]
125 fn test_jwks_config_serialization() {
126 let config = JwksConfig {
127 uri: "https://auth.example.com/.well-known/jwks.json".to_owned(),
128 refresh_interval_seconds: 300,
129 max_backoff_seconds: 3600,
130 };
131
132 let json = serde_json::to_string_pretty(&config).unwrap();
133 let deserialized: JwksConfig = serde_json::from_str(&json).unwrap();
134 assert_eq!(deserialized.uri, config.uri);
135 assert_eq!(
136 deserialized.refresh_interval_seconds,
137 config.refresh_interval_seconds
138 );
139 assert_eq!(deserialized.max_backoff_seconds, config.max_backoff_seconds);
140 }
141
142 #[test]
143 fn test_auth_config_to_validation_config() {
144 let auth_config = AuthConfig {
145 leeway_seconds: 30,
146 issuers: vec!["https://auth.example.com".to_owned()],
147 audiences: vec!["api".to_owned()],
148 require_exp: true,
149 jwks: None,
150 };
151 let validation_config = ValidationConfig::from(&auth_config);
152 assert_eq!(validation_config.allowed_issuers, auth_config.issuers);
153 assert_eq!(validation_config.allowed_audiences, auth_config.audiences);
154 assert_eq!(validation_config.leeway_seconds, auth_config.leeway_seconds);
155 assert!(validation_config.require_exp);
156 }
157
158 #[test]
159 fn test_require_exp_defaults_true_when_omitted() {
160 let json = r#"{"leeway_seconds": 60}"#;
161 let config: AuthConfig = serde_json::from_str(json).unwrap();
162 assert!(config.require_exp);
163 }
164
165 #[test]
166 fn test_require_exp_false_propagates_to_validation_config() {
167 let auth_config = AuthConfig {
168 require_exp: false,
169 ..Default::default()
170 };
171 let validation_config = ValidationConfig::from(&auth_config);
172 assert!(!validation_config.require_exp);
173 }
174
175 #[test]
176 fn test_jwks_config_defaults() {
177 let json = r#"{"uri": "https://example.com/jwks"}"#;
178 let config: JwksConfig = serde_json::from_str(json).unwrap();
179 assert_eq!(config.refresh_interval_seconds, 300);
180 assert_eq!(config.max_backoff_seconds, 3600);
181 }
182}