From 4829f48ce609f1809143217f5cddb7172378933d Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 25 Oct 2024 14:14:02 +0100 Subject: [PATCH] chore(ffi): Expose supported OIDC prompts in the login details. --- bindings/matrix-sdk-ffi/src/authentication.rs | 9 +++- bindings/matrix-sdk-ffi/src/client.rs | 43 ++++++++++++++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/authentication.rs b/bindings/matrix-sdk-ffi/src/authentication.rs index 8540ca3b644..a2e41a5f9cf 100644 --- a/bindings/matrix-sdk-ffi/src/authentication.rs +++ b/bindings/matrix-sdk-ffi/src/authentication.rs @@ -19,13 +19,14 @@ use matrix_sdk::{ }; use url::Url; -use crate::client::{Client, SlidingSyncVersion}; +use crate::client::{Client, OidcPrompt, SlidingSyncVersion}; #[derive(uniffi::Object)] pub struct HomeserverLoginDetails { pub(crate) url: String, pub(crate) sliding_sync_version: SlidingSyncVersion, pub(crate) supports_oidc_login: bool, + pub(crate) supported_oidc_prompts: Vec, pub(crate) supports_password_login: bool, } @@ -46,6 +47,12 @@ impl HomeserverLoginDetails { self.supports_oidc_login } + /// The prompts advertised by the authentication issuer for use in the login + /// URL. + pub fn supported_oidc_prompts(&self) -> Vec { + self.supported_oidc_prompts.clone() + } + /// Whether the current homeserver supports the password login flow. pub fn supports_password_login(&self) -> bool { self.supports_password_login diff --git a/bindings/matrix-sdk-ffi/src/client.rs b/bindings/matrix-sdk-ffi/src/client.rs index f44134fa0ba..79bb0bccec7 100644 --- a/bindings/matrix-sdk-ffi/src/client.rs +++ b/bindings/matrix-sdk-ffi/src/client.rs @@ -266,7 +266,31 @@ impl Client { impl Client { /// Information about login options for the client's homeserver. pub async fn homeserver_login_details(&self) -> Arc { - let supports_oidc_login = self.inner.oidc().fetch_authentication_issuer().await.is_ok(); + let oidc = self.inner.oidc(); + let (supports_oidc_login, supported_oidc_prompts) = match oidc + .fetch_authentication_issuer() + .await + { + Ok(issuer) => match &oidc.given_provider_metadata(&issuer).await { + Ok(metadata) => { + let prompts = metadata + .prompt_values_supported + .as_ref() + .map_or_else(Vec::new, |prompts| prompts.iter().map(Into::into).collect()); + + (true, prompts) + } + Err(error) => { + error!("Failed to fetch OIDC provider metadata: {error}"); + (true, Default::default()) + } + }, + Err(error) => { + error!("Failed to fetch authentication issuer: {error}"); + (false, Default::default()) + } + }; + let supports_password_login = self.supports_password_login().await.ok().unwrap_or(false); let sliding_sync_version = self.sliding_sync_version(); @@ -274,6 +298,7 @@ impl Client { url: self.homeserver(), sliding_sync_version, supports_oidc_login, + supported_oidc_prompts, supports_password_login, }) } @@ -1758,7 +1783,7 @@ impl TryFrom for SdkSlidingSyncVersion { } } -#[derive(uniffi::Enum)] +#[derive(Clone, uniffi::Enum)] pub enum OidcPrompt { /// The Authorization Server must not display any authentication or consent /// user interface pages. @@ -1790,6 +1815,20 @@ pub enum OidcPrompt { Unknown { value: String }, } +impl From<&SdkOidcPrompt> for OidcPrompt { + fn from(value: &SdkOidcPrompt) -> Self { + match value { + SdkOidcPrompt::None => Self::None, + SdkOidcPrompt::Login => Self::Login, + SdkOidcPrompt::Consent => Self::Consent, + SdkOidcPrompt::SelectAccount => Self::SelectAccount, + SdkOidcPrompt::Create => Self::Create, + SdkOidcPrompt::Unknown(value) => Self::Unknown { value: value.to_owned() }, + _ => Self::Unknown { value: value.to_string() }, + } + } +} + impl From for SdkOidcPrompt { fn from(value: OidcPrompt) -> Self { match value {