Highlights
A single architectural refactor that closes four open issues by giving the credential provider and the form authenticator distinct, simpler responsibilities. See PR #136 for the full diff.
Bug fixes
Decouple isConfiguredFor from realm flow scanning (#129)
EmailAuthenticatorCredentialProvider.isConfiguredFor no longer walks every authentication flow in the realm to read per-execution config. It now returns true only when the user has a stored email-authenticator credential. The provider's contract is independent of the flow configuration, which was the architectural concern raised in #129.
Account console no longer shows a phantom credential (#108)
Because isConfiguredFor only reports true when a credential actually exists, userCredentialMetadatas is empty for users who have not enrolled. The "always active" entry described in #108 is gone.
Admin-provisioned users are no longer blocked by the setup screen (#112)
EmailAuthenticatorForm.configuredFor is now derived purely from user.getEmail(). Any user with an email is eligible to receive an OTP without a prior enrolment step, restoring the pre-#107 experience for admin-enforced 2FA.
Plugin appears in "Try Another Way" alternatives (#50)
With the form reporting configuredFor == true for any user with an email, Keycloak now lists Email OTP as a selectable option when it sits alongside other alternatives such as TOTP.
Behavioural changes
EmailAuthenticatorForm.setRequiredActionsis now a no-op. Theemail-authenticator-setuprequired action remains available for voluntary enrolment via the account console, but the login flow never forces it.- The
skipSetupauthenticator-config property is removed from the admin UI because it no longer has a behavioural effect. The constants inEmailConstantsare kept as@Deprecatedso existing realm configurations that still contain the key deserialize cleanly — no migration required.
Upgrade notes
- No database migration required.
- If you previously relied on
skipSetup = falseto force enrolment before the OTP step, that pathway no longer exists. Users with an email now go straight to the OTP form; users without an email still surface the missing-email error at challenge time. Enrolment via the account console continues to work for users who want to register a credential explicitly.
Verification
mvn test→ 66/66 unit tests pass on the merged commit.
Compatibility
- Keycloak: 26.x (same as 26.4.1)
- Java: 17+
Full changelog: v26.4.1...v26.4.2