Repository navigation
Looking for guidance on a clean self-service MFA and recovery code design #54659
Replies: 1 comment
|
Most of this is doable with built-ins. The exception is cleaning up recovery codes, which needs a small bit of code. I checked against 26.8.1. Leftover codes still triggering 2FA. The condition now only counts OTP/WebAuthn, while alternative sub-flows are still walked when building the "Try another way" list (source). I read this from the code but haven't run this exact flow, so test it first. Invalidating codes. Nothing built in: deleting a credential removes just that one. It matters more than it looks, because "Add Recovery Codes" on Configure OTP skips setup when codes already exist, so a user who re-enables MFA keeps the old set. The smallest fix I can see is an event listener on Multiple devices work natively. Each OTP credential is separate and has a label. The Account Console adds and removes them one by one, and the OTP login form shows a device picker when there's more than one. Preferred method. The default alternative follows the order of the user's stored credentials (source). But the Account REST reorder endpoints are commented out (here), so today only the Admin API can change it. That's #12102. |
Uh oh!
There was an error while loading. Please reload this page.
Hi everyone!
I’m currently designing a self-service MFA solution for a B2B application using Keycloak. I’ve spent quite some time exploring the built-in authentication flows, required actions, recovery codes, and existing community extensions, but I keep running into limitations with each approach.
Before going down the route of custom development, I’d really appreciate some guidance from the community on whether there’s a cleaner, more idiomatic way to approach this.
Keycloak version: We’re currently targeting Keycloak 26.8.x, but we’re flexible about the version and happy to upgrade if a newer release offers a better solution.
What I’m trying to achieve
The goal is to give users control over their own MFA configuration while keeping recovery secure and predictable.
Ideally, I’d like the following behavior:
I’m flexible about the implementation and even the overall approach. These are the outcomes I’m aiming for, not necessarily strict implementation requirements.
What I’ve explored so far
The built-in Condition - User Configured works well for optional MFA. However, if the user removes their last OTP credential while recovery codes remain configured, Keycloak can still require recovery codes at login.
This creates an awkward state where the user has effectively disabled their authenticator but is still required to consume recovery codes on subsequent logins.
I found the Add Recovery Codes option in the Configure OTP required action, which is almost exactly the behavior I want during enrollment.
Unfortunately, there doesn’t seem to be an equivalent mechanism for automatically removing recovery codes when the last regular MFA credential is deleted.
The delete_credential AIA is great because the user can remove credentials through Keycloak itself.
However, it only removes one credential at a time. Chaining two AIAs through frontend redirects (first removing recovery codes, then the last OTP credential) feels fragile and introduces intermediate states.
Using the Admin REST API would be another option, but I’d prefer not to lose the distinction between user-initiated actions and administrative operations in the audit trail.
I’d also like users to be able to register and remove individual MFA devices without affecting their other credentials.
I haven’t found a straightforward self-service approach for managing the preferred authentication method or device. The Admin API supports credential ordering, but this doesn’t seem to be exposed through the standard Account Console.
I’ve also looked into projects such as keycloak-mfa-plugins, particularly because we may want to support email-based OTP in the future.
I’m open to using an existing extension if it provides a more complete approach to MFA enrollment, method selection, credential management, and recovery.
What I’d appreciate guidance on
Is there a recommended Keycloak-native approach, authentication flow configuration, or existing community extension that would cover these requirements without having to implement significant custom credential-management logic?
In particular, I’m interested in:
I’d prefer to avoid maintaining custom Java extensions if possible, but I’m open to different approaches if there’s a well-established solution.
Related discussions
Has anyone implemented a similar setup, or would you recommend approaching the overall MFA design differently?
Thanks in advance for any pointers or suggestions!
All reactions