feat: add Keycloak authentication for dashboard and API endpoints (#2)
Dashboard: OAuth2/OIDC login flow with PKCE, session-based auth middleware protecting all server function endpoints, check-auth server function for frontend auth state, login page gate in AppShell, user info in sidebar. Agent API: JWT validation middleware using Keycloak JWKS endpoint, conditionally enabled when KEYCLOAK_URL and KEYCLOAK_REALM are set. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com> Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
56
compliance-dashboard/src/infrastructure/keycloak_config.rs
Normal file
56
compliance-dashboard/src/infrastructure/keycloak_config.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use super::error::DashboardError;
|
||||
|
||||
/// Keycloak OpenID Connect settings.
|
||||
#[derive(Debug)]
|
||||
pub struct KeycloakConfig {
|
||||
pub url: String,
|
||||
pub realm: String,
|
||||
pub client_id: String,
|
||||
pub redirect_uri: String,
|
||||
pub app_url: String,
|
||||
}
|
||||
|
||||
impl KeycloakConfig {
|
||||
pub fn from_env() -> Result<Self, DashboardError> {
|
||||
Ok(Self {
|
||||
url: required_env("KEYCLOAK_URL")?,
|
||||
realm: required_env("KEYCLOAK_REALM")?,
|
||||
client_id: required_env("KEYCLOAK_CLIENT_ID")?,
|
||||
redirect_uri: required_env("REDIRECT_URI")?,
|
||||
app_url: required_env("APP_URL")?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn auth_endpoint(&self) -> String {
|
||||
format!(
|
||||
"{}/realms/{}/protocol/openid-connect/auth",
|
||||
self.url, self.realm
|
||||
)
|
||||
}
|
||||
|
||||
pub fn token_endpoint(&self) -> String {
|
||||
format!(
|
||||
"{}/realms/{}/protocol/openid-connect/token",
|
||||
self.url, self.realm
|
||||
)
|
||||
}
|
||||
|
||||
pub fn userinfo_endpoint(&self) -> String {
|
||||
format!(
|
||||
"{}/realms/{}/protocol/openid-connect/userinfo",
|
||||
self.url, self.realm
|
||||
)
|
||||
}
|
||||
|
||||
pub fn logout_endpoint(&self) -> String {
|
||||
format!(
|
||||
"{}/realms/{}/protocol/openid-connect/logout",
|
||||
self.url, self.realm
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn required_env(name: &str) -> Result<String, DashboardError> {
|
||||
std::env::var(name)
|
||||
.map_err(|_| DashboardError::Config(format!("{name} is required but not set")))
|
||||
}
|
||||
Reference in New Issue
Block a user