diff --git a/changelog.d/2226.feature.md b/changelog.d/2226.feature.md new file mode 100644 index 000000000..5eec8f1f1 --- /dev/null +++ b/changelog.d/2226.feature.md @@ -0,0 +1 @@ +Continuwuity now supports configuring additional trusted audience values for deployments using OIDC with an IDP that sends them. Contributed by @ginger diff --git a/conduwuit-example.toml b/conduwuit-example.toml index 24c5159ca..ae37686ed 100644 --- a/conduwuit-example.toml +++ b/conduwuit-example.toml @@ -2319,6 +2319,16 @@ # #additional_scopes = [] +# Additional trusted audiences that Continuwuity will accept in the `aud` +# claim of the OIDC token returned by the IDP. If your identity +# provider includes other values in the `aud` claim in addition to the +# client ID, they must be listed here for Continuwuity to accept them. +# +# Most deployments will not need to set this, because most identity +# providers only include the client ID in the `aud` claim by default. +# +#additional_trusted_audiences = [] + # The name of the identity provider. If this is set, the login page's # button reads "Continue with " instead of just "Continue". # diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index 3fc9566ca..02497681c 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -17,7 +17,7 @@ use either::{ use figment::providers::{Env, Format, Toml}; pub use figment::{Figment, value::Value as FigmentValue}; use lettre::message::Mailbox; -use openidconnect::{ClientId, ClientSecret, Scope}; +use openidconnect::{Audience, ClientId, ClientSecret, Scope}; use regex::RegexSet; use ruma::{ OwnedRoomId, OwnedRoomOrAliasId, OwnedServerName, OwnedServerSigningKeyId, OwnedUserId, @@ -2800,6 +2800,18 @@ pub struct OidcConfig { #[serde(default)] pub additional_scopes: Vec, + /// Additional trusted audiences that Continuwuity will accept in the `aud` + /// claim of the OIDC token returned by the IDP. If your identity + /// provider includes other values in the `aud` claim in addition to the + /// client ID, they must be listed here for Continuwuity to accept them. + /// + /// Most deployments will not need to set this, because most identity + /// providers only include the client ID in the `aud` claim by default. + /// + /// default: [] + #[serde(default)] + pub additional_trusted_audiences: BTreeSet, + /// The name of the identity provider. If this is set, the login page's /// button reads "Continue with " instead of just "Continue". /// diff --git a/src/service/oidc/mod.rs b/src/service/oidc/mod.rs index e8492c9a8..a7bed9847 100644 --- a/src/service/oidc/mod.rs +++ b/src/service/oidc/mod.rs @@ -275,7 +275,7 @@ impl Service { session: PendingSession, response: AuthorizationCodeResponse, ) -> Result { - let Some(OidcClient { machine, client, .. }) = self.client.as_ref() else { + let Some(OidcClient { machine, client, config, .. }) = self.client.as_ref() else { return Err("Delegated authentication is not enabled on this server."); }; @@ -293,7 +293,8 @@ impl Service { .await .map_err(|err| { error!(error=?err, "Failed to exchange OIDC authorization code"); - "Code exchange failed." + "Code exchange failed. The identity provider may be unreachable. Contact your \ + homeserver's administrator." })?; let Some(id_token) = token_response.id_token() else { @@ -301,8 +302,14 @@ impl Service { return Err(Self::SERVER_MISCONFIGURED); }; + let verifier = machine + .id_token_verifier() + .set_other_audience_verifier_fn(|audience| { + config.additional_trusted_audiences.contains(audience) + }); + let claims = id_token - .claims(&machine.id_token_verifier(), &session.nonce) + .claims(&verifier, &session.nonce) .map_err(|err| { error!("Failed to verify id token claims: {err}"); Self::SERVER_MISCONFIGURED