From 27e7dc68a8c3fad1148c8e36538b0209405f9587 Mon Sep 17 00:00:00 2001 From: Livio Spring Date: Wed, 26 Oct 2022 10:20:01 +0200 Subject: [PATCH] feat: allow disabling the mfa setup prompt (#4575) * feat: allow disabling the mfa setup prompt * e2e: disable mfa prompt Co-authored-by: Max Peintner --- .../login-policy/login-policy.component.ts | 50 +++++++++---------- .../manage/console/instance-settings.mdx | 11 ++++ e2e/docker-compose.yaml | 2 +- .../eventsourcing/eventstore/auth_request.go | 3 ++ 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/console/src/app/modules/policies/login-policy/login-policy.component.ts b/console/src/app/modules/policies/login-policy/login-policy.component.ts index dfea830837..7b40b6d0fd 100644 --- a/console/src/app/modules/policies/login-policy/login-policy.component.ts +++ b/console/src/app/modules/policies/login-policy/login-policy.component.ts @@ -45,11 +45,11 @@ export class LoginPolicyComponent implements OnInit { public InfoSectionType: any = InfoSectionType; public PasswordlessType: any = PasswordlessType; public lifetimeForm: UntypedFormGroup = this.fb.group({ - passwordCheckLifetime: [{ disabled: true, value: 240 }, [Validators.required]], - externalLoginCheckLifetime: [{ disabled: true, value: 12 }, [Validators.required]], - mfaInitSkipLifetime: [{ disabled: true, value: 720 }, [Validators.required]], - secondFactorCheckLifetime: [{ disabled: true, value: 12 }, [Validators.required]], - multiFactorCheckLifetime: [{ disabled: true, value: 12 }, [Validators.required]], + passwordCheckLifetime: [{ disabled: true }, [Validators.required]], + externalLoginCheckLifetime: [{ disabled: true }, [Validators.required]], + mfaInitSkipLifetime: [{ disabled: true }, [Validators.required]], + secondFactorCheckLifetime: [{ disabled: true }, [Validators.required]], + multiFactorCheckLifetime: [{ disabled: true }, [Validators.required]], }); constructor( private toast: ToastService, @@ -67,29 +67,29 @@ export class LoginPolicyComponent implements OnInit { this.loading = false; this.passwordCheckLifetime?.setValue( - this.loginData.passwordCheckLifetime?.seconds ? this.loginData.passwordCheckLifetime?.seconds / 60 / 60 : 240, + this.loginData.passwordCheckLifetime?.seconds ? this.loginData.passwordCheckLifetime?.seconds / 60 / 60 : 0, ); this.externalLoginCheckLifetime?.setValue( this.loginData.externalLoginCheckLifetime?.seconds ? this.loginData.externalLoginCheckLifetime?.seconds / 60 / 60 - : 12, + : 0, ); this.mfaInitSkipLifetime?.setValue( - this.loginData.mfaInitSkipLifetime?.seconds ? this.loginData.mfaInitSkipLifetime?.seconds / 60 / 60 : 720, + this.loginData.mfaInitSkipLifetime?.seconds ? this.loginData.mfaInitSkipLifetime?.seconds / 60 / 60 : 0, ); this.secondFactorCheckLifetime?.setValue( this.loginData.secondFactorCheckLifetime?.seconds ? this.loginData.secondFactorCheckLifetime?.seconds / 60 / 60 - : 12, + : 0, ); this.multiFactorCheckLifetime?.setValue( this.loginData.multiFactorCheckLifetime?.seconds ? this.loginData.multiFactorCheckLifetime?.seconds / 60 / 60 - : 12, + : 0, ); } }) @@ -158,19 +158,19 @@ export class LoginPolicyComponent implements OnInit { mgmtreq.setDisableLoginWithEmail(this.loginData.disableLoginWithEmail); mgmtreq.setDisableLoginWithPhone(this.loginData.disableLoginWithPhone); - const pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 240) * 60 * 60); + const pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 0) * 60 * 60); mgmtreq.setPasswordCheckLifetime(pcl); - const elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 12) * 60 * 60); + const elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 0) * 60 * 60); mgmtreq.setExternalLoginCheckLifetime(elcl); - const misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 720) * 60 * 60); + const misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 0) * 60 * 60); mgmtreq.setMfaInitSkipLifetime(misl); - const sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 12) * 60 * 60); + const sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 0) * 60 * 60); mgmtreq.setSecondFactorCheckLifetime(sfcl); - const mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60); + const mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 0) * 60 * 60); mgmtreq.setMultiFactorCheckLifetime(mficl); mgmtreq.setAllowDomainDiscovery(this.loginData.allowDomainDiscovery); @@ -189,19 +189,19 @@ export class LoginPolicyComponent implements OnInit { mgmtreq.setDisableLoginWithEmail(this.loginData.disableLoginWithEmail); mgmtreq.setDisableLoginWithPhone(this.loginData.disableLoginWithPhone); - const pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 240) * 60 * 60); + const pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 0) * 60 * 60); mgmtreq.setPasswordCheckLifetime(pcl); - const elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 12) * 60 * 60); + const elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 0) * 60 * 60); mgmtreq.setExternalLoginCheckLifetime(elcl); - const misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 720) * 60 * 60); + const misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 0) * 60 * 60); mgmtreq.setMfaInitSkipLifetime(misl); - const sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 12) * 60 * 60); + const sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 0) * 60 * 60); mgmtreq.setSecondFactorCheckLifetime(sfcl); - const mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60); + const mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 0) * 60 * 60); mgmtreq.setMultiFactorCheckLifetime(mficl); mgmtreq.setAllowDomainDiscovery(this.loginData.allowDomainDiscovery); @@ -221,19 +221,19 @@ export class LoginPolicyComponent implements OnInit { adminreq.setDisableLoginWithEmail(this.loginData.disableLoginWithEmail); adminreq.setDisableLoginWithPhone(this.loginData.disableLoginWithPhone); - const admin_pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 240) * 60 * 60); + const admin_pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 0) * 60 * 60); adminreq.setPasswordCheckLifetime(admin_pcl); - const admin_elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 12) * 60 * 60); + const admin_elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 0) * 60 * 60); adminreq.setExternalLoginCheckLifetime(admin_elcl); - const admin_misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 720) * 60 * 60); + const admin_misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 0) * 60 * 60); adminreq.setMfaInitSkipLifetime(admin_misl); - const admin_sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 12) * 60 * 60); + const admin_sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 0) * 60 * 60); adminreq.setSecondFactorCheckLifetime(admin_sfcl); - const admin_mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60); + const admin_mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 0) * 60 * 60); adminreq.setMultiFactorCheckLifetime(admin_mficl); adminreq.setAllowDomainDiscovery(this.loginData.allowDomainDiscovery); adminreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames); diff --git a/docs/docs/guides/manage/console/instance-settings.mdx b/docs/docs/guides/manage/console/instance-settings.mdx index 7f1c61f7b5..ed1528f4df 100644 --- a/docs/docs/guides/manage/console/instance-settings.mdx +++ b/docs/docs/guides/manage/console/instance-settings.mdx @@ -109,6 +109,17 @@ Secondfactors: - OTP (One Time Password), Authenticator Apps like Google/Microsoft Authenticator, Authy, etc. - U2F (Universal Second Factor), e.g FaceID, WindowsHello, Fingerprint, Hardwaretokens like Yubikey +### Login Lifetimes + +Configure the different lifetimes checks for the login process: + +- **Password Check Lifetime** specifies after which period a user has to reenter his password during the login process +- **External Login Check Lifetime** specifies after which period a user will be redirected to the IDP during the login process +- **Multifactor Init Lifetime** specifies after which period a user will be prompted to setup a 2-Factor / Multi Factor during the login process (value 0 will deactivate the prompt) +- **Second Factor Check Lifetime** specifies after which period a user has to revalidate the 2-Factor during the login process +- **External Login Check Lifetime** specifies after which period a user has to revalidate the Multi Factor during the login process + + ## Identity Providers You can configure all kinds of external identity providers for identity brokering, which support OIDC (OpenID Connect). diff --git a/e2e/docker-compose.yaml b/e2e/docker-compose.yaml index 84f60872f1..1fa76a0985 100644 --- a/e2e/docker-compose.yaml +++ b/e2e/docker-compose.yaml @@ -6,9 +6,9 @@ services: image: '${ZITADEL_IMAGE:-ghcr.io/zitadel/zitadel:latest}' command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled' environment: - ZITADEL_EXTERNALSECURE: false ZITADEL_DATABASE_COCKROACH_HOST: db ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORDCHANGEREQUIRED: false + ZITADEL_DEFAULTINSTANCE_LOGINPOLICY_MFAINITSKIPLIFETIME: 0 depends_on: db: condition: 'service_healthy' diff --git a/internal/auth/repository/eventsourcing/eventstore/auth_request.go b/internal/auth/repository/eventsourcing/eventstore/auth_request.go index d1370508cd..1379798f55 100644 --- a/internal/auth/repository/eventsourcing/eventstore/auth_request.go +++ b/internal/auth/repository/eventsourcing/eventstore/auth_request.go @@ -1106,6 +1106,9 @@ func (repo *AuthRequestRepo) mfaSkippedOrSetUp(user *user_model.UserView, reques if user.MFAMaxSetUp > domain.MFALevelNotSetUp { return true } + if request.LoginPolicy.MFAInitSkipLifetime == 0 { + return true + } return checkVerificationTime(user.MFAInitSkipped, request.LoginPolicy.MFAInitSkipLifetime) }