oidc integration

Reviewed-on: #11
This commit was merged in pull request #11.
This commit is contained in:
2026-01-06 20:11:22 +00:00
parent ede9567e09
commit bf9c688e6b
39 changed files with 2853 additions and 516 deletions

View File

@@ -1,7 +1,32 @@
#[cfg(feature = "smart-features")]
use notes_infra::factory::{EmbeddingProvider, VectorProvider};
use serde::{Deserialize, Serialize};
use std::env;
/// Authentication mode - determines how the API authenticates requests
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum AuthMode {
/// Session-based authentication using cookies (default for backward compatibility)
#[default]
Session,
/// JWT-based authentication using Bearer tokens
Jwt,
/// Support both session and JWT authentication (try JWT first, then session)
Both,
}
impl AuthMode {
/// Parse auth mode from string
pub fn from_str(s: &str) -> Self {
match s.to_lowercase().as_str() {
"jwt" => AuthMode::Jwt,
"both" => AuthMode::Both,
_ => AuthMode::Session,
}
}
}
/// Server configuration
#[derive(Debug, Clone)]
pub struct Config {
@@ -16,6 +41,34 @@ pub struct Config {
#[cfg(feature = "smart-features")]
pub vector_provider: VectorProvider,
pub broker_url: String,
pub secure_cookie: bool,
pub db_max_connections: u32,
pub db_min_connections: u32,
// OIDC configuration
pub oidc_issuer: Option<String>,
pub oidc_client_id: Option<String>,
pub oidc_client_secret: Option<String>,
pub oidc_redirect_url: Option<String>,
pub oidc_resource_id: Option<String>,
// Auth mode configuration
pub auth_mode: AuthMode,
// JWT configuration
pub jwt_secret: Option<String>,
pub jwt_issuer: Option<String>,
pub jwt_audience: Option<String>,
pub jwt_expiry_hours: u64,
/// Whether the application is running in production mode
pub is_production: bool,
/// Frontend URL for OIDC redirect (defaults to first CORS origin)
pub frontend_url: String,
}
impl Default for Config {
@@ -36,6 +89,21 @@ impl Default for Config {
collection: "notes".to_string(),
},
broker_url: "nats://localhost:4222".to_string(),
secure_cookie: false,
db_max_connections: 5,
db_min_connections: 1,
oidc_issuer: None,
oidc_client_id: None,
oidc_client_secret: None,
oidc_redirect_url: None,
oidc_resource_id: None,
auth_mode: AuthMode::Session,
jwt_secret: None,
jwt_issuer: None,
jwt_audience: None,
jwt_expiry_hours: 24,
is_production: false,
frontend_url: "http://localhost:5173".to_string(),
}
}
}
@@ -89,6 +157,46 @@ impl Config {
let broker_url =
env::var("BROKER_URL").unwrap_or_else(|_| "nats://localhost:4222".to_string());
let secure_cookie = env::var("SECURE_COOKIE")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(false);
let db_max_connections = env::var("DB_MAX_CONNECTIONS")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(5);
let db_min_connections = env::var("DB_MIN_CONNECTIONS")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(1);
let oidc_issuer = env::var("OIDC_ISSUER").ok();
let oidc_client_id = env::var("OIDC_CLIENT_ID").ok();
let oidc_client_secret = env::var("OIDC_CLIENT_SECRET").ok();
let oidc_redirect_url = env::var("OIDC_REDIRECT_URL").ok();
let oidc_resource_id = env::var("OIDC_RESOURCE_ID").ok();
// Auth mode configuration
let auth_mode = env::var("AUTH_MODE")
.map(|s| AuthMode::from_str(&s))
.unwrap_or_default();
// JWT configuration
let jwt_secret = env::var("JWT_SECRET").ok();
let jwt_issuer = env::var("JWT_ISSUER").ok();
let jwt_audience = env::var("JWT_AUDIENCE").ok();
let jwt_expiry_hours = env::var("JWT_EXPIRY_HOURS")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(24);
let is_production = env::var("PRODUCTION")
.or_else(|_| env::var("RUST_ENV"))
.map(|v| v.to_lowercase() == "production" || v == "1" || v == "true")
.unwrap_or(false);
Self {
host,
port,
@@ -101,6 +209,22 @@ impl Config {
#[cfg(feature = "smart-features")]
vector_provider,
broker_url,
secure_cookie,
db_max_connections,
db_min_connections,
oidc_issuer,
oidc_client_id,
oidc_client_secret,
oidc_redirect_url,
oidc_resource_id,
auth_mode,
jwt_secret,
jwt_issuer,
jwt_audience,
jwt_expiry_hours,
is_production,
frontend_url: env::var("FRONTEND_URL")
.unwrap_or_else(|_| "http://localhost:5173".to_string()),
}
}
}