Last updated: September 2026
Classic MFA fatigue, the push-bombing attack where a user approves a prompt at 3am to make it stop, does not apply to a stock Keycloak realm, because Keycloak 26.x ships no authenticator that pushes an approval request to a device. The built-in second factors are TOTP and HOTP, WebAuthn and passkeys, recovery codes, X.509 client certificates and Kerberos, all of which the user initiates. The half of this attack pattern that does apply, to Keycloak as much as to any identity provider, is what happens after the helpdesk phone call: the attacker registers an authenticator they control and keeps access. So the hardening work here is not about push prompts. It is about who can enroll a credential, under what conditions, and whether you would see it in your events.
Two scoping notes before the detail. Microsoft’s September 2026 report, which is the freshest field evidence for this pattern, documents vishing, adversary-in-the-middle phishing and device-code abuse ending in attacker-controlled MFA enrollment. It does not discuss push bombing at all, so treat it as evidence for the enrollment half rather than the fatigue half. We covered the relayed-login and device-code side of that report in device code phishing and passkey lures, including the detection table for it. This post picks up at the enrollment surface.
Does MFA fatigue apply to a stock Keycloak realm?
Mostly not, and the reason is structural. An MFA fatigue attack needs a factor that can push an approval request to a device without the user asking for it. Reading the authenticator factories registered in the 26.7.4 source, the browser-facing set covers username and password forms, OTPFormAuthenticator for TOTP and HOTP, WebAuthnAuthenticator and WebAuthnPasswordlessAuthenticator, recovery authentication codes, X.509 and Kerberos, plus conditional executions for roles, scopes, credential type and level of authentication. Every one of them waits for the user to start.
There is no built-in approval prompt an attacker can trigger repeatedly. The closest thing Keycloak ships is CIBA, the OpenID Connect client-initiated backchannel authentication grant, which is genuinely decoupled and approval-shaped. Two things keep it dormant: it is opt-in per client through the oidc.ciba.grant.enabled setting, and the shipped HTTP authentication channel provider refuses to start unless you configure it with the URL of an external authentication device. If you do enable CIBA, the fatigue question moves to whatever device you pointed it at, not to Keycloak. Our CIBA walkthrough covers the flow.
Worth being precise about: this is a property of the built-in browser authenticators, not a guarantee about your deployment. A third-party push authenticator, a federated identity provider that does push, or an enabled CIBA channel each put the fatigue attack back on the table, and each belongs to that component rather than to Keycloak. Skycloak’s own email OTP extension is a factor outside the upstream list, though it is user-initiated rather than push.
Most published MFA fatigue guidance is written for Entra and Duo deployments, which is why so much of it is about number matching and push throttling. Those are real controls in those products. Copying that advice into a Keycloak hardening plan produces a list of settings that do not exist.
Why does enrollment survive a passkey rollout?
Because enrollment is the operation that creates trust, and it usually runs at a lower assurance level than the thing it protects. A user who has just proved they are themselves with a password and a one-time code can typically add a new authenticator. If that login was relayed through an attacker proxy, the attacker inherits the same ability.
Passkeys close the relay, for the reasons covered in the Keycloak passkeys and WebAuthn guide and in the device-code post above. What they do not govern is the enrollment path running alongside them. During a rollout, most realms keep password plus OTP available so nobody is locked out, and keep self-service enrollment open so people can adopt passkeys without a ticket. That combination is the window, and it stays open for as long as the migration takes. Our notes on migrating off SMS to passkeys cover the sequencing.
Microsoft’s report describes the payoff directly, writing that “the actor enrolled an MFA method under their control, typically by registering a new phone number, authenticator application, or software-based one-time password (OTP) token” (Microsoft Security Blog, “Passkey-themed social engineering leads to identity and cloud compromise,” 9 September 2026). Microsoft assesses the initial-access activity as used by a range of actors, including ones it tracks as Storm-3121 and Storm-3032.
How do you control authenticator enrollment in Keycloak?
Three levers, in increasing order of friction.
Know what disabling a required action actually does
Keycloak’s required actions are the enrollment surface. The set registered in 26.7.4 includes CONFIGURE_TOTP, webauthn-register, webauthn-register-passwordless, delete_credential and CONFIGURE_RECOVERY_AUTHN_CODES, along with the profile and email actions. Each can be enabled or disabled per realm, and each can be marked as a default action applied to new users.
The common misconception is that disabling an action leaves it available to administrators. It does not. In 26.7.4, AuthenticationManager resolves a required action by alias and returns nothing when the provider model is disabled, so an action an administrator assigns to a specific user is skipped at the next login, and the kc_action path logs that the requested action is disabled. Disabling is realm-wide and absolute, for admins and users alike. Treat it as switching that enrollment method off, not as restricting it.
delete_credential deserves its own look while you are in there. Removing an authenticator is as security-relevant as adding one, since it is how an attacker drops the legitimate factor after adding their own.
Put a higher bar in front of credential management
The account console is a client like any other, which means the browser flow it uses is yours to configure. Keycloak ships a conditional-level-of-authentication execution for level-of-authentication conditions and a conditional-credential execution that branches on which credential the user actually presented. Between them you can require that reaching credential management involves a stronger factor than reaching a normal application.
The practical shape is: normal apps accept the standard flow, the account console requires a higher ACR, and a user who signed in with password and OTP is asked for something stronger before they can add an authenticator. Our step-up authentication guide covers the ACR and LoA mechanics, and the broader patterns are in MFA integration patterns for enterprise applications. For populations that should not self-manage credentials at all, removing the manage-account role on the account client is the blunter version of the same idea.
Treat a helpdesk-initiated reset as a privileged operation
The vishing route usually ends at a human rather than a login form. Someone calls, sounds plausible, and a support agent resets the factor, with no exploit involved anywhere in the chain.
That makes the permissions on your support tooling part of your MFA posture. Two specifics for Keycloak. Audit who holds manage-users on the realm-management client, since that role covers credential reset, and check for anyone granted the separate reset-password permission directly if you run the v2 admin permissions model. Then audit the impersonation role, which realm admins hold through the realm-admin composite but which is also commonly granted on its own to support groups that deliberately do not hold realm-admin, so a review of realm-admin holders alone will not surface everyone who has it. Impersonation had its own vulnerability in this release line, covered in the CVE-2026-17526 impersonation escalation brief, and the day-to-day practice is in running impersonation safely for support.
A callback policy does more work here than any realm setting. Agents who verify by calling the number in the directory, rather than the number that called them, remove the pretext entirely.
Which Keycloak events tell you an authenticator was registered?
Since Keycloak 26, credential changes emit generic events: UPDATE_CREDENTIAL and REMOVE_CREDENTIAL, with the kind of credential carried in a credential_type attribute. The CONFIGURE_TOTP required action fires UPDATE_CREDENTIAL directly, and delete_credential records the credential id it removed.
The older type-specific events, UPDATE_TOTP, REMOVE_TOTP, UPDATE_PASSWORD and their error variants, are marked deprecated in the 26.7.4 EventType source and still fire alongside the generic ones for backwards compatibility. Detections written against the old names work today and will break on a future major version. Detections written against the new ones catch password, OTP and WebAuthn registration in a single rule, which is what this attack needs.
The alert worth building is narrow: a credential registration shortly after a login from an unfamiliar location, or a registration followed quickly by removal of an existing credential. The event table in the device-code post covers the surrounding signals, and shipping events somewhere that can correlate them is covered in forwarding Keycloak events to a SIEM.
What about OTP guessing and lockout?
Keycloak’s brute force detection covers repeated failed authentication and is worth enabling, though it has a known shape problem: the counters are per user, so a distributed attempt against many accounts from one source is less visible than it should be. We documented that in the IP-based brute force protection gap.
For this threat model, lockout cuts both ways, since an attacker who can trigger lockouts gains a plausible reason for the victim to call the helpdesk. That is the loop this post is about, and it is why enrollment controls and support-desk verification matter more than tightening the lockout threshold.
Frequently asked questions
Does Keycloak support push notification MFA?
Not in the box. Keycloak 26.x ships TOTP and HOTP, WebAuthn and passkeys, recovery codes, X.509 and Kerberos. CIBA backchannel authentication is the one decoupled approval flow, and it is off per client by default and requires an external authentication device you configure. Push approval otherwise needs a third-party integration or an upstream identity provider.
How do I stop users from registering new MFA methods in Keycloak?
Disabling the required action turns that enrollment method off for everyone, administrators included, so it is a blunt instrument. The usable middle ground is requiring a higher level of authentication for the account console with the conditional-level-of-authentication execution, or removing manage-account for populations that should not self-manage credentials.
Are passkeys enough to stop helpdesk vishing?
No. Passkeys break the relayed-login step, because a WebAuthn signature is bound to the relying party. They do not govern who may enroll a new authenticator, or what your support desk does when someone calls claiming to be locked out. Both need separate controls.
Which Keycloak event shows a new authenticator being added?
UPDATE_CREDENTIAL, with the kind of credential in the credential_type attribute. Deprecated per-type events such as UPDATE_TOTP still fire alongside it for compatibility, but new detections should target the generic event, which covers password, OTP and WebAuthn registration in one rule.
Is MFA fatigue a real risk for Keycloak deployments?
Only where a push-capable factor has been added, through a custom authenticator, an enabled CIBA channel, or a federated identity provider that uses push. For realms running the built-in authenticators, the realistic risks are enrollment abuse after a successful phish and social engineering of the support desk.
Sources
- Microsoft Security Blog, “Passkey-themed social engineering leads to identity and cloud compromise,” 9 September 2026, https://www.microsoft.com/en-us/security/blog/2026/09/09/passkey-themed-social-engineering-leads-identity-cloud-compromise/
- Keycloak, authenticator and required-action registrations,
EventTypeandAuthenticationManagerat release tag 26.7.4, https://github.com/keycloak/keycloak/releases/tag/26.7.4 - Keycloak, “Keycloak 26.0.0 released,” upgrading notes for the generic
UPDATE_CREDENTIALandREMOVE_CREDENTIALevents, https://www.keycloak.org/2024/10/keycloak-2600-released