tuwunel_api/oidc/
auth_metadata.rs1use axum::{Json, extract::State, response::IntoResponse};
2use serde::{Deserialize, Serialize};
3use tuwunel_core::Result;
4
5use super::ACCOUNT_MANAGEMENT_ACTIONS_SUPPORTED;
6
7#[derive(Debug, Serialize, Deserialize)]
8struct ProviderMetadata {
9 issuer: String,
10 authorization_endpoint: String,
11 token_endpoint: String,
12 registration_endpoint: Option<String>,
13 revocation_endpoint: Option<String>,
14 jwks_uri: String,
15 userinfo_endpoint: Option<String>,
16 account_management_uri: Option<String>,
17 account_management_actions_supported: Option<Vec<String>>,
18 response_types_supported: Vec<String>,
19 response_modes_supported: Option<Vec<String>>,
20 grant_types_supported: Option<Vec<String>>,
21 code_challenge_methods_supported: Option<Vec<String>>,
22 token_endpoint_auth_methods_supported: Option<Vec<String>>,
23 scopes_supported: Option<Vec<String>>,
24 subject_types_supported: Option<Vec<String>>,
25 id_token_signing_alg_values_supported: Option<Vec<String>>,
26 prompt_values_supported: Option<Vec<String>>,
27 claim_types_supported: Option<Vec<String>>,
28 claims_supported: Option<Vec<String>>,
29}
30
31pub(crate) async fn openid_configuration_route(
32 State(services): State<crate::State>,
33) -> Result<impl IntoResponse> {
34 let issuer = services.oauth.get_server()?.issuer_url()?;
35 let base = issuer.trim_end_matches('/').to_owned();
36
37 Ok(Json(ProviderMetadata {
38 issuer,
39
40 authorization_endpoint: format!("{base}/_tuwunel/oidc/authorize"),
41
42 registration_endpoint: Some(format!("{base}/_tuwunel/oidc/registration")),
43
44 userinfo_endpoint: Some(format!("{base}/_tuwunel/oidc/userinfo")),
45
46 token_endpoint: format!("{base}/_tuwunel/oidc/token"),
47
48 jwks_uri: format!("{base}/_tuwunel/oidc/jwks"),
49
50 account_management_uri: Some(format!("{base}/_tuwunel/oidc/account")),
51
52 revocation_endpoint: Some(format!("{base}/_tuwunel/oidc/revoke")),
53
54 response_modes_supported: Some(vec!["query".to_owned(), "fragment".to_owned()]),
55
56 response_types_supported: vec!["code".to_owned()],
57
58 code_challenge_methods_supported: Some(vec!["S256".to_owned()]),
59
60 id_token_signing_alg_values_supported: Some(vec!["ES256".to_owned()]),
61
62 prompt_values_supported: Some(vec![]),
63
64 subject_types_supported: Some(vec!["public".to_owned()]),
65
66 claim_types_supported: Some(vec!["normal".to_owned()]),
67
68 grant_types_supported: Some(vec![
69 "authorization_code".to_owned(),
70 "refresh_token".to_owned(),
71 ]),
72
73 token_endpoint_auth_methods_supported: Some(vec![
74 "none".to_owned(),
75 "client_secret_basic".to_owned(),
76 "client_secret_post".to_owned(),
77 ]),
78
79 scopes_supported: Some(vec![
80 "openid".to_owned(),
81 "urn:matrix:org.matrix.msc2967.client:api:*".to_owned(),
82 "urn:matrix:org.matrix.msc2967.client:device:*".to_owned(),
83 ]),
84
85 account_management_actions_supported: Some(
86 ACCOUNT_MANAGEMENT_ACTIONS_SUPPORTED
87 .iter()
88 .map(ToString::to_string)
89 .collect(),
90 ),
91
92 claims_supported: Some(vec![
93 "iss".to_owned(),
94 "sub".to_owned(),
95 "aud".to_owned(),
96 "exp".to_owned(),
97 "iat".to_owned(),
98 "nonce".to_owned(),
99 ]),
100 }))
101}