use std::time::Duration;
const DEFAULT_JWT_EXPIRATION_SECS: u64 = 300;
const DEFAULT_SIGNING_SERVICE_URL: &str = "http://localhost:8000/signature";
const DEFAULT_HTTP_TIMEOUT_SECS: u64 = 3;
#[derive(Debug, Clone)]
pub struct OnesOidcConfig {
pub http_timeout: Duration,
pub user_agent: Option<String>,
pub jwt_expiration_secs: u64,
pub signing_service_url: String,
pub validate_jwt_audience: bool,
}
impl Default for OnesOidcConfig {
fn default() -> Self {
Self {
http_timeout: Duration::from_secs(DEFAULT_HTTP_TIMEOUT_SECS),
user_agent: Some(format!("ones-oidc/{}", env!("CARGO_PKG_VERSION"))),
jwt_expiration_secs: DEFAULT_JWT_EXPIRATION_SECS,
signing_service_url: DEFAULT_SIGNING_SERVICE_URL.to_string(),
validate_jwt_audience: false,
}
}
}
impl OnesOidcConfig {
pub fn with_timeout(timeout: Duration) -> Self {
Self {
http_timeout: timeout,
..Default::default()
}
}
pub fn with_signing_service_url(url: String) -> Self {
Self {
signing_service_url: url,
..Default::default()
}
}
pub fn with_jwt_audience_validation(enabled: bool) -> Self {
Self {
validate_jwt_audience: enabled,
..Default::default()
}
}
pub fn with_jwt_expiration(expiration_secs: u64) -> Self {
Self {
jwt_expiration_secs: expiration_secs,
..Default::default()
}
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.http_timeout = timeout;
self
}
pub fn signing_service_url(mut self, url: String) -> Self {
self.signing_service_url = url;
self
}
pub fn jwt_audience_validation(mut self, enabled: bool) -> Self {
self.validate_jwt_audience = enabled;
self
}
pub fn jwt_expiration(mut self, expiration_secs: u64) -> Self {
self.jwt_expiration_secs = expiration_secs;
self
}
pub fn from_env() -> Self {
let mut config = Self::default();
if let Ok(timeout_str) = std::env::var("ONES_OIDC_TIMEOUT_SECS") {
if let Ok(timeout_secs) = timeout_str.parse::<u64>() {
config.http_timeout = Duration::from_secs(timeout_secs);
}
}
if let Ok(signing_url) = std::env::var("ONES_OIDC_SIGNING_SERVICE_URL") {
config.signing_service_url = signing_url;
}
if let Ok(validate_str) = std::env::var("ONES_OIDC_VALIDATE_JWT_AUDIENCE") {
config.validate_jwt_audience = validate_str.to_lowercase() == "true";
}
if let Ok(exp_str) = std::env::var("ONES_OIDC_JWT_EXPIRATION_SECS") {
if let Ok(exp_secs) = exp_str.parse::<u64>() {
config.jwt_expiration_secs = exp_secs;
}
}
config
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = OnesOidcConfig::default();
assert_eq!(config.jwt_expiration_secs, DEFAULT_JWT_EXPIRATION_SECS);
assert_eq!(config.signing_service_url, DEFAULT_SIGNING_SERVICE_URL);
assert!(!config.validate_jwt_audience);
}
#[test]
fn test_builder_pattern() {
let config = OnesOidcConfig::default()
.timeout(Duration::from_secs(10))
.signing_service_url("https://production.example.com/signature".to_string())
.jwt_audience_validation(true)
.jwt_expiration(600);
assert_eq!(config.http_timeout, Duration::from_secs(10));
assert_eq!(config.signing_service_url, "https://production.example.com/signature");
assert!(config.validate_jwt_audience);
assert_eq!(config.jwt_expiration_secs, 600);
}
#[test]
fn test_from_env() {
std::env::set_var("ONES_OIDC_TIMEOUT_SECS", "5");
std::env::set_var("ONES_OIDC_SIGNING_SERVICE_URL", "https://test.example.com/sign");
std::env::set_var("ONES_OIDC_VALIDATE_JWT_AUDIENCE", "true");
std::env::set_var("ONES_OIDC_JWT_EXPIRATION_SECS", "120");
let config = OnesOidcConfig::from_env();
assert_eq!(config.http_timeout, Duration::from_secs(5));
assert_eq!(config.signing_service_url, "https://test.example.com/sign");
assert!(config.validate_jwt_audience);
assert_eq!(config.jwt_expiration_secs, 120);
std::env::remove_var("ONES_OIDC_TIMEOUT_SECS");
std::env::remove_var("ONES_OIDC_SIGNING_SERVICE_URL");
std::env::remove_var("ONES_OIDC_VALIDATE_JWT_AUDIENCE");
std::env::remove_var("ONES_OIDC_JWT_EXPIRATION_SECS");
}
}