Configure Authentication browser flow for IdP, Password+2FA and Passkey

I am trying to achieve the following Browser Authentication flow in Keycloak (Version 26.4.7). Users usually should use the external Identity Provider (Google Workspace).

But it is possible that the user can access realms/my-realm/account/ and set a password, 2FA-methods or a passkey. If the user set’s a password, a second factor (2FA) should be provided for authentication. If the User sets a Passkey (passwordless, webauthn-passwordless) nothing more is required for authentication.

  • If the user uses the external IdP (Google Workspace) authenticate the user.
  • If the user provides a username and password, ask for a second factor (Authenticator, Recovery-Codes or Passkey as webauthn-authenticator)
  • If the user logs in via Passkey (webauthn-passwordless) authenticate him without 2FA.

All methods work so far, but if i login via Passkey (webauthn-passwordless) i always get asked for 2FA! And i can’t figure out how to configure the Browser flow to not ask for a second factor with Passkey for the live of me!

I duplicated the browser Authentication flow to browser-2fa, bound it to “Browser flow” and made the following changes:

  • Conditional 2FA is set to Required
    • Condition - user configrued is default (Required)
    • Condition - credential is default (Rrequired)
      • Credentials is webauthn-passwordless (this is also default)
      • Included is Off (also default)
    • Step OTP Form (auth-top-form) is set to Alternative
    • Step WebAuthn Authenticatior (webauthn-authenticator) is set to Alternative
    • Step Recovery Authentication Code Form (auth-recovery-authn-code-form is set to Alternative

As far as i understand the flow, the Condition - credential checks if a Passkey (webauthn-passwordless) is used and due to Included Off should return false (from the Tooltip: “… If this option is false (which should read Off), the condition is evaluated in the opposite way, it will be true if none of the credentials configured have been used, and false if one or more of them have been used.“) as “one or more” of the provided credentials is used with a Passkey and the whole flow Conditional 2FA should not be executed! But apparently this is not the case. What do i miss here?

When you set a subflow from conditional to required, the conditions are ignored. There’s a reason why the subflow has conditional requirement. That’s why a user must provide an additonal factor, even when he/she has authenticated with passwordless passkey.

1 Like

Danke Niko! That’s a helpful tidbit.

So how would i go about to create the desired flow? Do i have to create a seperate sub-flow and check if webauthn-passwordless is used or not?

Also, when i set Conditional 2FA back to it’s default Conditional, 2FA only get’s asked if it is configured but not enforced at authentication.

Work with the default flow, that’s all you need in terms of the flow. Set all the 2fa options to alternative if you want them to be used.

For enforcing one of them, it gets more tricky… you have the following custom-made options:

  1. Implement a custom event listener, which sets the required action Configure OTP to all users who are currently setting a password credential but have not an OTP yet.
  2. Overwrite the Configure OTP action with a custom impl in a way that it gets “auto registering” (the evaluateTriggermethod), if a user authenticates through password, but has no OTP configured yet. Could become a bit tricky, I wouldn’t recommend this.
  3. Use a custom required action like this one: keycloak-extensions-demo/requiredaction/src/main/java/dasniko/keycloak/requiredaction/MfaEnrollmentAction.java at main · dasniko/keycloak-extensions-demo · GitHub which you can use to enforce a user to configure at least one of the configured MFA options. This action is self-registering after you have enabled it. But it has currently no check for current authentication method. So, also tricky.

First option might be an easy one.
No matter what, I recommend to configure the Configure OTP action with the new option to enforce to configure recovery codes right after the OTP config has been done. This way, the user has automatically a fallback if he changed or lost his phone.