diff --git a/src/service/uiaa/mod.rs b/src/service/uiaa/mod.rs index acd3dd86..71e03d63 100644 --- a/src/service/uiaa/mod.rs +++ b/src/service/uiaa/mod.rs @@ -11,7 +11,7 @@ use database::{Deserialized, Json, Map}; use ruma::{ CanonicalJsonValue, DeviceId, OwnedDeviceId, OwnedUserId, UserId, api::client::{ - error::ErrorKind, + error::{ErrorKind, StandardErrorBody}, uiaa::{AuthData, AuthType, Password, UiaaInfo, UserIdentifier}, }, }; @@ -104,6 +104,7 @@ pub fn create( } #[implement(Service)] +#[allow(clippy::useless_let_if_seq)] pub async fn try_auth( &self, user_id: &UserId, @@ -163,17 +164,39 @@ pub async fn try_auth( let user_id = user_id_from_username; // Check if password is correct + let mut password_verified = false; + + // First try local password hash verification if let Ok(hash) = self.services.users.password_hash(&user_id).await { - let hash_matches = hash::verify_password(password, &hash).is_ok(); - if !hash_matches { - uiaainfo.auth_error = Some(ruma::api::client::error::StandardErrorBody { - kind: ErrorKind::forbidden(), - message: "Invalid username or password.".to_owned(), - }); - return Ok((false, uiaainfo)); + password_verified = hash::verify_password(password, &hash).is_ok(); + } + + // If local password verification failed, try LDAP authentication + #[cfg(feature = "ldap")] + if !password_verified && self.services.config.ldap.enable { + // Search for user in LDAP to get their DN + if let Ok(dns) = self.services.users.search_ldap(&user_id).await { + if let Some((user_dn, _is_admin)) = dns.first() { + // Try to authenticate with LDAP + password_verified = self + .services + .users + .auth_ldap(user_dn, password) + .await + .is_ok(); + } } } + if !password_verified { + uiaainfo.auth_error = Some(StandardErrorBody { + kind: ErrorKind::forbidden(), + message: "Invalid username or password.".to_owned(), + }); + + return Ok((false, uiaainfo)); + } + // Password was correct! Let's add it to `completed` uiaainfo.completed.push(AuthType::Password); }, @@ -197,7 +220,7 @@ pub async fn try_auth( }, | Err(e) => { error!("ReCaptcha verification failed: {e:?}"); - uiaainfo.auth_error = Some(ruma::api::client::error::StandardErrorBody { + uiaainfo.auth_error = Some(StandardErrorBody { kind: ErrorKind::forbidden(), message: "ReCaptcha verification failed.".to_owned(), }); @@ -210,7 +233,7 @@ pub async fn try_auth( if tokens.contains(t.token.trim()) { uiaainfo.completed.push(AuthType::RegistrationToken); } else { - uiaainfo.auth_error = Some(ruma::api::client::error::StandardErrorBody { + uiaainfo.auth_error = Some(StandardErrorBody { kind: ErrorKind::forbidden(), message: "Invalid registration token.".to_owned(), });