98 lines
3.4 KiB
Rust
98 lines
3.4 KiB
Rust
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
|
*/
|
|
|
|
use common::{Server, auth::oauth::oidc::Userinfo};
|
|
use http_proto::*;
|
|
use serde::Serialize;
|
|
use std::future::Future;
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub struct OpenIdMetadata {
|
|
pub issuer: String,
|
|
pub authorization_endpoint: String,
|
|
pub token_endpoint: String,
|
|
pub userinfo_endpoint: String,
|
|
pub jwks_uri: String,
|
|
pub registration_endpoint: String,
|
|
pub device_authorization_endpoint: String,
|
|
pub scopes_supported: &'static [&'static str],
|
|
pub response_types_supported: &'static [&'static str],
|
|
pub subject_types_supported: &'static [&'static str],
|
|
pub grant_types_supported: &'static [&'static str],
|
|
pub id_token_signing_alg_values_supported: &'static [&'static str],
|
|
pub claims_supported: &'static [&'static str],
|
|
pub code_challenge_methods_supported: &'static [&'static str],
|
|
}
|
|
|
|
pub trait OpenIdHandler: Sync + Send {
|
|
fn handle_userinfo_request(
|
|
&self,
|
|
account_id: u32,
|
|
) -> impl Future<Output = trc::Result<HttpResponse>> + Send;
|
|
|
|
fn handle_oidc_metadata(
|
|
&self,
|
|
req: &HttpRequest,
|
|
session: &HttpSessionData,
|
|
) -> impl Future<Output = trc::Result<HttpResponse>> + Send;
|
|
}
|
|
|
|
impl OpenIdHandler for Server {
|
|
async fn handle_userinfo_request(&self, account_id: u32) -> trc::Result<HttpResponse> {
|
|
let account = self.account(account_id).await?;
|
|
|
|
Ok(JsonResponse::new(Userinfo {
|
|
sub: Some(account_id.to_string()),
|
|
name: account.description().map(|d| d.to_string()),
|
|
preferred_username: Some(account.name().to_string()),
|
|
email: account.name().to_string().into(),
|
|
email_verified: true,
|
|
..Default::default()
|
|
})
|
|
.no_cache()
|
|
.into_http_response())
|
|
}
|
|
|
|
async fn handle_oidc_metadata(
|
|
&self,
|
|
req: &HttpRequest,
|
|
session: &HttpSessionData,
|
|
) -> trc::Result<HttpResponse> {
|
|
let base_url = HttpContext::new(session, req).resolve_response_url(self);
|
|
|
|
Ok(JsonResponse::new(OpenIdMetadata {
|
|
authorization_endpoint: format!("{base_url}/login",),
|
|
token_endpoint: format!("{base_url}/auth/token"),
|
|
userinfo_endpoint: format!("{base_url}/auth/userinfo"),
|
|
jwks_uri: format!("{base_url}/auth/jwks.json"),
|
|
registration_endpoint: format!("{base_url}/auth/register"),
|
|
device_authorization_endpoint: format!("{base_url}/auth/device"),
|
|
response_types_supported: &["code", "id_token", "id_token token"],
|
|
grant_types_supported: &[
|
|
"authorization_code",
|
|
"implicit",
|
|
"urn:ietf:params:oauth:grant-type:device_code",
|
|
],
|
|
scopes_supported: &["openid", "offline_access"],
|
|
subject_types_supported: &["public"],
|
|
id_token_signing_alg_values_supported: &[
|
|
"RS256", "RS384", "RS512", "ES256", "ES384", "PS256", "PS384", "PS512", "HS256",
|
|
"HS384", "HS512",
|
|
],
|
|
claims_supported: &[
|
|
"sub",
|
|
"name",
|
|
"preferred_username",
|
|
"email",
|
|
"email_verified",
|
|
],
|
|
code_challenge_methods_supported: &["S256"],
|
|
issuer: base_url.to_string(),
|
|
})
|
|
.into_http_response())
|
|
}
|
|
}
|