8000 Apply Trust Email when the IdP e-mail differs only in case by akasakariko · Pull Request #54837 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content

Apply Trust Email when the IdP e-mail differs only in case - #54837

Merged
pedroigor merged 4 commits into
keycloak:mainfrom
akasakariko:fix/broker-trust-email-uppercase-email
Nov 11, 2026
Merged

pedroigor merged 4 commits into
keycloak:mainfrom
akasakariko:fix/broker-trust-email-uppercase-email

Conversation

@akasakariko
@akasakariko akasakariko commented Nov 7, 2026 •
Copy link
Copy Markdown
Contributor

Problem

When an identity provider sends an e-mail address with uppercase letters and the first broker login shows the Review Profile form, the user profile lower-cases the address and IdpReviewProfileAuthenticator records that as an e-mail change made by the user, which sets UPDATE_PROFILE_EMAIL_CHANGED

AbstractIdentityProvider then skips Trust Email and creates the user with emailVerified=false, so a user of a trusted directory has to verify the address again on the first sign-in

Fix

A change of the e-mail attribute that is removed by the lower-casing of the user profile is no longer recorded as a change made by the user

The comparison uses the same KeycloakModelUtils.toLowerCaseSafe normalisation as the user profile, so a different address is still a change even when a case-insensitive comparison such as equalsIgnoreCase treats the characters as equal, for example the dotless ı and i

A change to a different address still requires verification

Tests

KcOidcBrokerTrustEmailUppercaseEmailTest brokers a user whose address is sent as Probe@gıthub.test with Trust Email and Verify email enabled and asserts that the sign-in completes and that the created user has a verified address

A second case submits probe@github.test, which differs from the provider address by the dotless ı against i, and asserts that the email verification page is shown, that the submitted address is stored with emailVerified=false and that the verification e-mail is addressed to it

Verified locally

  • testTrustEmailAppliedWhenEmailDiffersOnlyInCase and testChangedEmailRequiresVerification pass with this change, while the second case fails without it
  • an end-to-end run of a server with two realms reproduces emailVerified=false plus a VERIFY_EMAIL required action before the change and completes the sign-in with emailVerified=true after it, while a genuine e-mail change still triggers verification
  • KC_TEST_SERVER=embedded mvnw -pl tests/base -Dtest=KcOidcBrokerTrustEmailUppercaseEmailTest test passes
  • KC_TEST_SERVER=embedded mvnw -pl tests/base -Dtest=KcOidcBrokerTest test passes
  • KC_TEST_SERVER=embedded mvnw -pl tests/base -Dtest=KcOidcFirstBrokerLoginDetectExistingUserTest,IdpCreateUserIfUniqueAuthenticatorTest test passes
  • mvnw -pl services,tests/base spotless:check passes

Fixes #54775

@akasakariko
akasakariko requested a review from a team as a code owner November 7, 2026 08:53
Copilot AI balanced review requested due to automatic review settings November 7, 2026 08:53
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

The first-broker-login review profile stores the e-mail address of the brokered
user in lower case, which was wrongly recorded as an e-mail change made by the
user, so with Verify email enabled the address was created as unverified and
the user had to verify it again even though the identity provider is trusted

Closes keycloak#54775

Signed-off-by: KayanoLiam <Kayano04@outlook.jp>
@akasakariko
akasakariko force-pushed the fix/broker-trust-email-uppercase-email branch from 1515c23 to 2dbac48 Compare November 7, 2026 08:53
@oleksii-udovychenko oleksii-udovychenko left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akasakariko, should isCaseOnlyChange lower-case the IdP address and compare it with equals? Java's equalsIgnoreCase also treats some different letters as equal, for example the dotless ı and i, so a user can change the address in the Review Profile form to a different one and still get Trust Email.

The IdP sends probe@gıthub.test. If the user changes it to other@example.test, Keycloak creates the user with emailVerified=false. If the user changes it to probe@github.test, the user is created with probe@github.test and emailVerified=true. With this change reverted, the second address is emailVerified=false as well.

isCaseOnlyChange returns true when oldValue.get(0).equalsIgnoreCase(newValue), and the email branch then returns without setting UPDATE_PROFILE_EMAIL_CHANGED. The user profile lower-cases with KeycloakModelUtils::toLowerCaseSafe, and "gıthub".toLowerCase() stays gıthub, so the two checks disagree. EmailValidationUtil accepts \u0080 to \uFFFF in both parts of the address, so the IdP address passes validation.

How I tested:

  1. Copied KcOidcBrokerTrustEmailUppercaseEmailTest with the hardcoded email claim set to probe@gıthub.test, Trust Email and Verify email on.
  2. Submitted the Review Profile form with three addresses, and printed the created user's email and emailVerified.
  3. Ran it on this branch, and again with the IdpReviewProfileAuthenticator change reverted.

I ran this with the embedded server only.

Address submitted Expected Actual (this PR) Actual (change reverted)
probe@gıthub.test, unchanged (control) verified verified verified
other@example.test (control) not verified not verified not verified
probe@github.test not verified verified not verified

equalsIgnoreCase treats distinct letters such as the dotless 'ı' and 'i' as
equal, so a user could change the brokered e-mail to a different address in the
review profile form and still get Trust Email

Lower-case the IdP address with the same KeycloakModelUtils.toLowerCaseSafe the
user profile applies and compare it with equals, so only the normalization of
the address is ignored

Signed-off-by: KayanoLiam <Kayano04@outlook.jp>
Copilot AI balanced review requested due to automatic review settings November 9, 2026 01:16
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@akasakariko
Copy link
Copy Markdown
Contributor Author

@oleksii-udovychenko thanks, fixed in ead580f

isCaseOnlyChange now lower-cases the IdP address with KeycloakModelUtils::toLowerCaseSafe, the same normalisation the user profile applies, and compares it with equals, so probe@github.test is no longer treated as a case-only change of probe@gıthub.test

KcOidcBrokerTrustEmailUppercaseEmailTest now brokers Probe@gıthub.test; one case submits the address unchanged and completes the sign-in with a verified address, the other submits probe@github.test and asserts that the email verification page is shown and a verification e-mail is sent

Verified with the embedded server: the second case fails on the previous behaviour and passes with the change

The unit tests could not resolve surefire-junit4 3.5.6 from Maven Central and the download failed with 403 Forbidden

Signed-off-by: KayanoLiam <Kayano04@outlook.jp>
@martin-kanis martin-kanis left a comment •
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akasakariko Thanks for the PR and @oleksii-udovychenko for the suggestion.
The PR looks good to me, I have just one optional improvement, please see below.

The test only checked that the verification page was shown and an e-mail was
sent, so it could pass if the submitted address were discarded and the
verification went to the address of the identity provider instead

Also assert that the submitted address is stored unverified and that the
verification e-mail is addressed to it

Signed-off-by: KayanoLiam <Kayano04@outlook.jp>
Copilot AI balanced review requested due to automatic review settings November 10, 2026 14:12
@akasakariko
Copy link
Copy Markdown
Contributor Author

Updated in 1c201cd

testChangedEmailRequiresVerification now also asserts that the submitted address is stored with emailVerified=false and that the verification e-mail is addressed to it, so the test cannot pass if the submitted address were discarded and verification went to the provider address

Verified that the new assertions fail against the previous behaviour (expecting the provider address fails with expected: <probe@gıthub.test> but was: <probe@github.test>)

  • KC_TEST_SERVER=embedded mvnw -pl tests/base -Dtest=KcOidcBrokerTrustEmailUppercaseEmailTest test passes
  • KC_TEST_SERVER=embedded mvnw -pl tests/base -Dtest=KcOidcBrokerTest test passes
  • KC_TEST_SERVER=embedded mvnw -pl tests/base -Dtest=KcOidcFirstBrokerLoginDetectExistingUserTest,IdpCreateUserIfUniqueAuthenticatorTest test passes
  • mvnw -pl services,tests/base spotless:check passes

Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@martin-kanis martin-kanis left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akasakariko Thank you for addressing the comment. LGTM

@pedroigor
pedroigor merged commit 17f0c35 into keycloak:main Nov 11, 2026
96 checks passed
@pedroigor
Copy link
Copy Markdown
Contributor

Thanks, @akasakariko.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Trust Email is not applied when the IdP sends an email with uppercase letters and Review Profile is shown

5 participants

0