diff --git a/changelog.d/+oidc-provider-branding.feature.md b/changelog.d/+oidc-provider-branding.feature.md new file mode 100644 index 000000000..4d93c1ce6 --- /dev/null +++ b/changelog.d/+oidc-provider-branding.feature.md @@ -0,0 +1 @@ +Added the `provider_name` and `provider_icon` OIDC options, which show the identity provider's name and icon on the web login page. Contributed by @eleboucher. diff --git a/conduwuit-example.toml b/conduwuit-example.toml index 88be80ad6..2f67e041c 100644 --- a/conduwuit-example.toml +++ b/conduwuit-example.toml @@ -2271,6 +2271,20 @@ # #additional_scopes = [] +# The name of the identity provider. If this is set, the login page's +# button reads "Continue with " instead of just "Continue". +# +# example: "Kanidm" +# +#provider_name = + +# The URL of an icon for the identity provider, shown on the login page +# next to its name. +# +# example: "https://idm.example.com/pkg/img/logo-square.svg" +# +#provider_icon = + # Whether the user should be prompted to choose a localpart # when signing in for the first time. If this is `false`, Continuwuity # will attempt to use the value of the `preferred_username_claim` diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index e50c2ec74..419008e09 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -2749,6 +2749,18 @@ pub struct OidcConfig { #[serde(default)] pub additional_scopes: Vec, + /// The name of the identity provider. If this is set, the login page's + /// button reads "Continue with " instead of just "Continue". + /// + /// example: "Kanidm" + pub provider_name: Option, + + /// The URL of an icon for the identity provider, shown on the login page + /// next to its name. + /// + /// example: "https://idm.example.com/pkg/img/logo-square.svg" + pub provider_icon: Option, + /// Whether the user should be prompted to choose a localpart /// when signing in for the first time. If this is `false`, Continuwuity /// will attempt to use the value of the `preferred_username_claim` diff --git a/src/service/oidc/mod.rs b/src/service/oidc/mod.rs index b2f5bd4ee..e8492c9a8 100644 --- a/src/service/oidc/mod.rs +++ b/src/service/oidc/mod.rs @@ -219,6 +219,18 @@ impl Service { pub fn enabled(&self) -> bool { self.client.is_some() } + pub fn provider_name(&self) -> Option { + let OidcClient { config, .. } = self.client.as_ref().expect("oidc should be configured"); + + config.provider_name.clone() + } + + pub fn provider_icon(&self) -> Option { + let OidcClient { config, .. } = self.client.as_ref().expect("oidc should be configured"); + + config.provider_icon.clone() + } + pub fn restricted_profile_fields(&self) -> Vec { if let Some(config) = self.client.as_ref().map(|client| &client.config) && matches!(config.profile_key_import_mode, OidcProfileKeyImportMode::OnLogin) diff --git a/src/web/pages/account/login.rs b/src/web/pages/account/login.rs index b6af09f69..44f9592d2 100644 --- a/src/web/pages/account/login.rs +++ b/src/web/pages/account/login.rs @@ -61,6 +61,8 @@ enum LoginType { }, Oidc { redirect_url: Url, + provider_name: Option, + provider_icon: Option, }, } @@ -98,7 +100,11 @@ async fn route_login( .await .expect("should be able to serialize OIDC session"); - LoginType::Oidc { redirect_url } + LoginType::Oidc { + redirect_url, + provider_name: services.oidc.provider_name(), + provider_icon: services.oidc.provider_icon(), + } } else { LoginType::Interactive { registration_available: services diff --git a/src/web/pages/resources/login.css b/src/web/pages/resources/login.css index d36810727..fd6b93c09 100644 --- a/src/web/pages/resources/login.css +++ b/src/web/pages/resources/login.css @@ -7,6 +7,18 @@ } } +a.button.provider-button { + display: flex; + align-items: center; + justify-content: center; + gap: 0.5em; +} + +.provider-icon { + flex: none; + height: 2em; +} + .text-rule { display: flex; align-items: center; diff --git a/src/web/pages/templates/login.html.j2 b/src/web/pages/templates/login.html.j2 index 6017b6119..f862b6ea8 100644 --- a/src/web/pages/templates/login.html.j2 +++ b/src/web/pages/templates/login.html.j2 @@ -8,6 +8,19 @@ Log in {%- endblock -%} +{%- macro oidc_button(redirect_url, provider_name, provider_icon) -%} + + {% if let Some(icon) = provider_icon %} + + {% endif %} + {% if let Some(name) = provider_name %} + Continue with {{ name }} + {% else %} + Continue + {% endif %} + +{%- endmacro -%} + {%- block content -%} {% match login_type %} {% when LoginType::Interactive { .. } %} @@ -54,8 +67,8 @@ Log in {% endif %} Forgot your password? - {% when LoginType::Oidc { redirect_url } %} - Continue + {% when LoginType::Oidc { redirect_url, provider_name, provider_icon } %} + {{ oidc_button(redirect_url, provider_name, provider_icon) }} {% endmatch %} {% when LoginBody::Authenticated { user_card } %}

Confirm your identity

@@ -76,8 +89,8 @@ Log in - {% when LoginType::Oidc { redirect_url } %} - Continue + {% when LoginType::Oidc { redirect_url, provider_name, provider_icon } %} + {{ oidc_button(redirect_url, provider_name, provider_icon) }} {% endmatch %} {% endmatch %}