haste_server/auth_n/oidc/routes/
mod.rs1use crate::{
2 auth_n::oidc::middleware::{
3 AuthSessionValidationLayer, OIDCParameterInjectLayer, ParameterConfig, project_exists,
4 },
5 services::ServerState,
6};
7use axum::{
8 Router,
9 http::{
10 HeaderValue,
11 header::{CACHE_CONTROL, PRAGMA},
12 },
13 middleware,
14};
15use axum_extra::routing::RouterExt;
16use haste_fhir_search::SearchEngine;
17use haste_fhir_terminology::FHIRTerminology;
18use haste_repository::Repository;
19use std::sync::{Arc, LazyLock};
20use tower::ServiceBuilder;
21use tower_http::set_header::SetResponseHeaderLayer;
22
23mod authorize;
24pub mod discovery;
25pub mod federated;
26pub mod interactions;
27pub mod introspect;
28mod jwks;
29pub mod route_string;
30pub mod scope;
31pub mod style;
32pub mod token;
33
34static AUTHORIZE_PARAMETERS: LazyLock<Arc<ParameterConfig>> = LazyLock::new(|| {
35 Arc::new(ParameterConfig {
36 required_parameters: vec![
37 "client_id".to_string(),
38 "response_type".to_string(),
39 "state".to_string(),
40 "code_challenge".to_string(),
41 "code_challenge_method".to_string(),
42 ],
43 optional_parameters: vec![
44 "scope".to_string(),
45 "redirect_uri".to_string(),
46 "aud".to_string(),
48 "launch".to_string(),
50 ],
51 })
52});
53
54static LOGOUT_PARAMETERS: LazyLock<Arc<ParameterConfig>> = LazyLock::new(|| {
55 Arc::new(ParameterConfig {
56 required_parameters: vec!["client_id".to_string()],
57 optional_parameters: vec!["redirect_uri".to_string()],
58 })
59});
60
61pub fn create_router<
62 Repo: Repository + Send + Sync,
63 Search: SearchEngine + Send + Sync,
64 Terminology: FHIRTerminology + Send + Sync,
65>(
66 state: Arc<ServerState<Repo, Search, Terminology>>,
67) -> Router<Arc<ServerState<Repo, Search, Terminology>>> {
68 Router::new()
69 .merge(Router::new().typed_get(jwks::jwks_get))
70 .merge(Router::new().typed_get(style::smart_style_get))
71 .merge(federated::federated_router())
72 .nest(
73 "/auth",
74 Router::new()
75 .merge(
80 Router::new()
81 .typed_post(token::token)
82 .typed_post(introspect::introspect)
83 .route_layer(
84 ServiceBuilder::new()
85 .layer(SetResponseHeaderLayer::overriding(
86 CACHE_CONTROL,
87 HeaderValue::from_static("no-store"),
88 ))
89 .layer(SetResponseHeaderLayer::overriding(
90 PRAGMA,
91 HeaderValue::from_static("no-cache"),
92 )),
93 ),
94 )
95 .merge(
96 Router::new()
97 .merge(
98 Router::new()
99 .typed_post(authorize::authorize)
100 .typed_get(authorize::authorize)
101 .route_layer(ServiceBuilder::new().layer(
102 OIDCParameterInjectLayer::new((*AUTHORIZE_PARAMETERS).clone()),
103 )),
104 )
105 .merge(Router::new().typed_post(scope::scope_post))
108 .route_layer(
109 ServiceBuilder::new()
110 .layer(AuthSessionValidationLayer::new("interactions/login")),
111 ),
112 ),
113 )
114 .nest("/interactions", interactions::interactions_router())
115 .route_layer(
116 ServiceBuilder::new().layer(middleware::from_fn_with_state(state, project_exists)),
117 )
118}