diff --git a/.env.template b/.env.template index 449b73c3..baa12767 100644 --- a/.env.template +++ b/.env.template @@ -552,7 +552,7 @@ ## Optional Master password policy (minComplexity=[0-4]), `enforceOnLogin` is not supported at the moment. # SSO_MASTER_PASSWORD_POLICY='{"enforceOnLogin":false,"minComplexity":3,"minLength":12,"requireLower":false,"requireNumbers":false,"requireSpecial":false,"requireUpper":false}' -## Skip Vaultwarden 2FA for SSO: false (never), true (always), auto (only when the IdP returns ACR level 2) +## Skip Vaultwarden 2FA for SSO: false (never), true (always), auto (only when the IdP returns an MFA ACR/AMR claim) # SSO_SKIP_2FA=false ## Use sso only for authentication not the session lifecycle diff --git a/src/api/identity.rs b/src/api/identity.rs index 52bfc6a4..81e37017 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -355,7 +355,14 @@ async fn sso_login( let skip_2fa = match CONFIG.sso_skip_2fa().as_str() { "true" => true, - "auto" => user_infos.acr.as_deref() == Some(SSO_2FA_ACR), + "auto" => { + user_infos.acr.as_deref() == Some(SSO_2FA_ACR) + || user_infos.amr.as_ref().is_some_and(|amr| { + amr.iter().any(|method| { + matches!(method.as_str(), "mfa" | "otp" | "fido2" | "webauthn" | "hwk") + }) + }) + } _ => false, }; let twofactor_token = if skip_2fa { diff --git a/src/db/models/sso_auth.rs b/src/db/models/sso_auth.rs index 0bb9232f..958a85f1 100644 --- a/src/db/models/sso_auth.rs +++ b/src/db/models/sso_auth.rs @@ -36,6 +36,7 @@ pub struct OIDCAuthenticatedUser { pub email_verified: Option, pub user_name: Option, pub acr: Option, + pub amr: Option>, } impl_FromToSqlText!(OIDCAuthenticatedUser); diff --git a/src/sso.rs b/src/sso.rs index 33f1b005..6dcf3303 100644 --- a/src/sso.rs +++ b/src/sso.rs @@ -308,6 +308,9 @@ pub async fn exchange_code( email_verified, user_name: user_name.clone(), acr: id_claims.auth_context_ref().map(|acr| acr.as_str().to_string()), + amr: id_claims + .auth_method_refs() + .map(|amr| amr.iter().map(|method| method.as_str().to_string()).collect()), }; debug!("Authenticated user {authenticated_user:?}");