Add sso_default_provider_id option and defaulting behavior.

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk
2026-01-14 04:26:21 +00:00
parent 86fc42bba0
commit dfb65d771f
3 changed files with 80 additions and 8 deletions

View File

@@ -1,4 +1,4 @@
use std::{borrow::Cow, time::Duration};
use std::{borrow::Cow, net::IpAddr, time::Duration};
use axum::extract::State;
use axum_client_ip::InsecureClientIp;
@@ -63,6 +63,10 @@ struct GrantCookie<'a> {
static GRANT_SESSION_COOKIE: &str = "tuwunel_grant_session";
/// # `GET /_matrix/client/v3/login/sso/redirect`
///
/// A web-based Matrix client should instruct the users browser to navigate to
/// this endpoint in order to log in via SSO.
#[tracing::instrument(
name = "sso_login",
level = "debug",
@@ -70,16 +74,47 @@ static GRANT_SESSION_COOKIE: &str = "tuwunel_grant_session";
fields(%client),
)]
pub(crate) async fn sso_login_route(
State(_services): State<crate::State>,
State(services): State<crate::State>,
InsecureClientIp(client): InsecureClientIp,
_body: Ruma<sso_login::v3::Request>,
body: Ruma<sso_login::v3::Request>,
) -> Result<sso_login::v3::Response> {
Err!(Request(NotImplemented(
"sso_custom_providers_page has been enabled but this URL has not been overridden with \
any custom page listing the available providers..."
)))
if services.config.sso_custom_providers_page {
return Err!(Request(NotImplemented(
"sso_custom_providers_page has been enabled but this URL has not been overridden \
with any custom page listing the available providers..."
)));
}
if services.config.identity_provider.len() > 1 {
return Err!(Config(
"sso_default_provider_id",
"This must be set when using more than one identity provider."
));
}
let idp_id = services
.config
.identity_provider
.iter()
.next()
.map(|idp| idp.client_id.clone())
.unwrap_or_default();
let redirect_url = body.body.redirect_url;
handle_sso_login(&services, &client, idp_id, redirect_url)
.map_ok(|response| sso_login::v3::Response {
location: response.location,
cookie: response.cookie,
})
.await
}
/// # `GET /_matrix/client/v3/login/sso/redirect/{idpId}`
///
/// This endpoint is the same as /login/sso/redirect, though with an IdP ID from
/// the original identity_providers array to inform the server of which IdP the
/// client/user would like to continue with.
#[tracing::instrument(
name = "sso_login_with_provider",
level = "info",
@@ -95,7 +130,18 @@ pub(crate) async fn sso_login_with_provider_route(
InsecureClientIp(client): InsecureClientIp,
body: Ruma<sso_login_with_provider::v3::Request>,
) -> Result<sso_login_with_provider::v3::Response> {
let sso_login_with_provider::v3::Request { idp_id, redirect_url } = body.body;
let idp_id = body.body.idp_id;
let redirect_url = body.body.redirect_url;
handle_sso_login(&services, &client, idp_id, redirect_url).await
}
async fn handle_sso_login(
services: &Services,
_client: &IpAddr,
idp_id: String,
redirect_url: String,
) -> Result<sso_login_with_provider::v3::Response> {
let Ok(redirect_url) = redirect_url.parse::<Url>() else {
return Err!(Request(InvalidParam("Invalid redirect_url")));
};

View File

@@ -2139,6 +2139,19 @@ pub struct Config {
#[serde(default = "default_one_time_key_limit")]
pub one_time_key_limit: usize,
/// This option is relevant when more than one identity_provider has been
/// configured and `sso_custom_providers_page` is false. Set this option to
/// the `client_id` of the provider to use for requests to
/// `/_matrix/client/v3/login/sso/redirect` (the url lacks a `client_id`).
///
/// This *must* be configured for some clients (e.g. fluffychat) to work
/// properly when the above conditions require it.
///
/// When only one identity_provider is configured that will be used as the
/// default and this does not have to be set.
#[serde(default)]
pub sso_default_provider_id: String,
/// Setting this option to true replaces the list of identity providers on
/// the client's login screen with a single button "Sign in with single
/// sign-on" linking to the URL `/_matrix/client/v3/login/sso/redirect`. The

View File

@@ -1834,6 +1834,19 @@
#
#one_time_key_limit = 256
# This option is relevant when more than one identity_provider has been
# configured and `sso_custom_providers_page` is false. Set this option to
# the `client_id` of the provider to use for requests to
# `/_matrix/client/v3/login/sso/redirect` (the url lacks a `client_id`).
#
# This *must* be configured for some clients (e.g. fluffychat) to work
# properly when the above conditions require it.
#
# When only one identity_provider is configured that will be used as the
# default and this does not have to be set.
#
#sso_default_provider_id = false
# Setting this option to true replaces the list of identity providers on
# the client's login screen with a single button "Sign in with single
# sign-on" linking to the URL `/_matrix/client/v3/login/sso/redirect`. The