Restrict marking email as verified to explicit email verification flow#50946
Restrict marking email as verified to explicit email verification flow#50946gaoyikeshuer wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Restricts implicit email verification during reset, account linking, and execute-actions flows.
Changes:
- Makes reset-flow verification opt-in.
- Separates broker-link confirmation from explicit email verification.
- Adds coverage for reset and execute-actions behavior.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
ResetPasswordTest.java |
Tests reset verification behavior. |
AbstractFirstBrokerLoginTest.java |
Tests broker-link verification flows. |
UserEmailTest.java |
Tests execute-actions email verification. |
ResetCredentialEmail.java |
Adds configurable reset verification. |
IdpEmailVerificationAuthenticator.java |
Separates broker and verification email notes. |
IdpVerifyAccountLinkActionTokenHandler.java |
Stops link confirmation from verifying email. |
ExecuteActionsActionTokenHandler.java |
Verifies only when explicitly requested. |
2848be0 to
ed7dff6
Compare
ed7dff6 to
4480dc6
Compare
4480dc6 to
3a812a5
Compare
3a812a5 to
072d8c6
Compare
072d8c6 to
9e5ba4c
Compare
9e5ba4c to
5816484
Compare
|
|
||
| Previously, some flows marked the email of a user as verified even though their purpose was not email verification. | ||
| This could make an account registered by a different party than the owner of the email address look trusted. | ||
| An email is now marked as verified only when the user completes an email verification. |
There was a problem hiding this comment.
Thanks @mabartos ! The issue is about the flows toggled the emailVerified by accident as a side effect nobody asked for them. but these two spots are the opposite, that they only run when an admin turned on Trust Email, which is off by default. I will add a line to the upgrading note to not overpromise causing misunderstanding.
5816484 to
2986dd8
Compare
| This changes the behavior of identity provider account linking by email, of admin-initiated action emails that do not include the *Verify Email* action, | ||
| and of the verifiable credential offer emails of the experimental OID4VCI feature. |
2986dd8 to
7df3183
Compare
|
|
||
| driver2.navigate().to(url); | ||
| waitForPage(driver, "your email address has been verified already.", false); | ||
| waitForPage(driver, "has been confirmed already.", false); |
|
@gaoyikeshuer Based on your screenshot, it seems that the title is the same as the description. I'd say it's a bug - the title should be brief and the details described in the sub-test(description). But it might be a follow-up issue. |
7df3183 to
ea3f706
Compare
Thanks! I've fixed the description and title part |
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.adapter.servlet.SAMLServletAdapterTest#employeeSigPostNoIdpKeyTestNoKeyNameInKeyInfoKeycloak CI - Adapter IT Strict Cookies |
ea3f706 to
17bf1a6
Compare
Closes keycloak#50622 Signed-off-by: Yike Gao <yikegao8@gmail.com>
17bf1a6 to
e9e30fd
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractFirstBrokerLoginTest.java:1202
- This assertion still waits on
driver, which is already showing the expected page from the preceding navigation, so thedriver2replay is never validated. Wait ondriver2to cover the second-browser behavior.
waitForPage(driver, "account linking already confirmed", false);
themes/src/main/resources/theme/base/login/messages/messages_en.properties:377
- This existing key is translated in community bundles, and many translations still claim the email was verified (for example,
messages_de.properties:309). Consequently the false verification claim remains for non-English users; use a new key with English fallback or update the translations.
identityProviderLinkSuccess=You successfully confirmed linking your account with {0} account {1}. Please go back to your original browser and continue there with the login.
| emailLinkIdp2=Haven''t received the email? | ||
| emailLinkIdp3=to re-send the email. | ||
| emailLinkIdp4=If you already verified the email in a different browser | ||
| emailLinkIdp4=If you already confirmed linking the account in a different browser |
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.oauth.ClientAuthPostMethodTest#testPostAuthenticationNotAllowedWhenBasicRequestedorg.keycloak.testsuite.oauth.ClientAuthPostMethodTest#testBasicAuthenticationNotAllowedWhenPostRequestedorg.keycloak.testsuite.forms.BrowserFlowTest#testUserWithOneAdditionalFactorOtpSuccessorg.keycloak.testsuite.forms.MultipleTabsLoginTest#testEmptyBaseUrlKeycloak CI - Forms IT (firefox) org.keycloak.testsuite.forms.MultipleTabsLoginTest#multipleTabsParallelLoginTestKeycloak CI - Forms IT (firefox) |
| This changes the behavior of identity provider account linking by email, of admin-initiated action emails that do not include the *Verify Email* action, | ||
| and of the verifiable credential offer emails of the experimental OID4VCI feature. |
| UserModel user = tokenContext.getAuthenticationSession().getAuthenticatedUser(); | ||
| // verify user email as we know it is valid as this entry point would never have gotten here. | ||
| user.setEmailVerified(true); | ||
| if (token.getRequiredActions().contains(UserModel.RequiredAction.VERIFY_EMAIL.name())) { |
There was a problem hiding this comment.
Even when this is in the list of required actions, it does not say it is completed, right? Shouldn't be really the place where it's set only after the email verification?
The weakness is the emailVerified couldd transition to true as a side effect of flows which purpose is not email verification. With this PR, the email of a user is marked as verified only by an explicit email verification
after the fix, the toggle will only be turned on after user finished the verification step:
Screen.Recording.2026-07-17.at.14.43.00.mov
master branch:
Screen.Recording.2026-07-20.at.13.08.08.mov
the difference between master branch and fix is: on master branch, the user just click confirm linking to the current exist account, but the verified Email toggle is on as a side effect, which is an vulnerability. the fix has an extra step, once you land on a Verify email page, a second email arrives, email verified stays OFF until user click the second link. also the page now says "Account linking confirmed" instead of the false "verified" claim.
Closes #50622