1#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
2#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc)]
3use crate::routes::{route_get_oidc_callback, route_post_oidc};
4use axum::{
5 Extension, Router,
6 routing::{get, post},
7};
8pub use config::OidcConfig;
9use openidconnect::{CsrfToken, Nonce, PkceCodeVerifier};
10use serde::{Deserialize, Serialize};
11pub use user_store::UserStore;
12
13mod config;
14mod error;
15mod routes;
16mod user_store;
17
18const SESSION_KEY_OIDC_STATE: &str = "oidc_state";
19
20#[derive(Debug, Deserialize, Serialize)]
21struct OidcState {
22 state: CsrfToken,
23 nonce: Nonce,
24 pkce_verifier: PkceCodeVerifier,
25 redirect_uri: Option<String>,
26}
27
28#[derive(Debug, Clone)]
29pub struct OidcServiceConfig {
30 pub default_redirect_path: &'static str,
31 pub session_key_user_id: &'static str,
32 pub callback_path: &'static str,
33}
34
35#[derive(Debug, Deserialize, Serialize)]
36struct GroupAdditionalClaims {
37 #[serde(default)]
38 groups: Option<Vec<String>>,
39}
40
41impl openidconnect::AdditionalClaims for GroupAdditionalClaims {}
42
43pub fn oidc_router<US: UserStore>(
44 config: OidcConfig,
45 service_config: OidcServiceConfig,
46 user_store: US,
47) -> Router {
48 Router::new()
49 .route("/", post(route_post_oidc))
50 .route("/callback", get(route_get_oidc_callback::<US>))
51 .layer(Extension(user_store))
52 .layer(Extension(config))
53 .layer(Extension(service_config))
54}