✨ Keycloak - Map multiple IdP users to a single user via custom multi-value attribute#2598
Conversation
…ti-IdP user linking Agent-Logs-Url: https://github.com/sequentech/step/sessions/5cef1d48-5e8a-40c9-9642-9434ff744db5 Co-authored-by: xalsina-sequent <173030604+xalsina-sequent@users.noreply.github.com>
Agent-Logs-Url: https://github.com/sequentech/step/sessions/5cef1d48-5e8a-40c9-9642-9434ff744db5 Co-authored-by: xalsina-sequent <173030604+xalsina-sequent@users.noreply.github.com>
|
Thank you for your contribution! Before we can merge this PR, we need you to sign our Contributor License Agreement (CLA). You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot. |
|
|
@copilot There's an error when adding the Authentication to a flow. keycloak | 2026-04-29 11:11:17,463 INFO [org.hibernate.orm.jdbc.batch] (executor-thread-7) HHH100503: On release of batch it still contained JDBC statements |
Agent-Logs-Url: https://github.com/sequentech/step/sessions/2f7aa4a3-f3f4-48ad-bac0-8283baa2f90c Co-authored-by: xalsina-sequent <173030604+xalsina-sequent@users.noreply.github.com>
Fixed in c8e05d8. The PROVIDER_ID |
| "CustomAttributeIdpLinkingAuthenticator: brokerContext.attributes=%s", | ||
| brokerContext.getAttributes()); |
| List<UserModel> matchingUsers = | ||
| session | ||
| .users() | ||
| .searchForUserByUserAttributeStream(realm, userAttributeName, incomingIdentifier) |
| if (matchingUsers.isEmpty()) { | ||
| log.infof( | ||
| "CustomAttributeIdpLinkingAuthenticator: no user found with attribute '%s'='%s'," | ||
| + " proceeding with next step", | ||
| userAttributeName, incomingIdentifier); | ||
| context.attempted(); | ||
| return; | ||
| } | ||
|
|
||
| if (matchingUsers.size() > 1) { | ||
| log.errorf( | ||
| "CustomAttributeIdpLinkingAuthenticator: %d users found with attribute '%s'='%s'," | ||
| + " failing to prevent ambiguous account linking", | ||
| matchingUsers.size(), userAttributeName, incomingIdentifier); | ||
| context.failure(AuthenticationFlowError.IDENTITY_PROVIDER_ERROR); |
| 1. Open the duplicnewated flow. | ||
| 2. Click **Add step** inside the appropriate sub-flow. | ||
| 3. Search for **Custom Attribute IdP Identity Linking** and add it. | ||
| 4. Set the requirement to **REQUIRED** if you want the flow to | ||
| fail when no match is found or **ALTERNATIVE** (the authenticator will call `attempted()` when no | ||
| matching user is found, allowing the next step to run, if you fant to create a user if not found for example). |
| ## Step 2 – Create the First Broker Login Flow | ||
|
|
||
| In this step we will create `sequent first broker login multivalue` flow directly. | ||
|
|
||
| 1. Navigate to **Authentication** → **Flows**. | ||
| 2. Click on create flow | ||
| 3. Give the new flow a descriptive name such as `sequent first broker login multivalue`. | ||
|
|
||
| --- | ||
|
|
||
| ## Step 3 – Add the Custom Authenticator to the Flow | ||
|
|
||
| 1. Open the duplicnewated flow. | ||
| 2. Click **Add step** inside the appropriate sub-flow. | ||
| 3. Search for **Custom Attribute IdP Identity Linking** and add it. | ||
| 4. Set the requirement to **REQUIRED** if you want the flow to | ||
| fail when no match is found or **ALTERNATIVE** (the authenticator will call `attempted()` when no | ||
| matching user is found, allowing the next step to run, if you fant to create a user if not found for example). |
| log.debugf( | ||
| "CustomAttributeIdpLinkingAuthenticator: brokerContext.attributes=%s", | ||
| brokerContext.getAttributes()); |
| if (matchingUsers.isEmpty()) { | ||
| log.infof( | ||
| "CustomAttributeIdpLinkingAuthenticator: no user found with attribute '%s'='%s'," | ||
| + " proceeding with next step", | ||
| userAttributeName, incomingIdentifier); | ||
| context.attempted(); |
|
|
||
| ## Step 3 – Add the Custom Authenticator to the Flow | ||
|
|
||
| 1. Open the duplicnewated flow. |
| 3. Search for **Custom Attribute IdP Identity Linking** and add it. | ||
| 4. Set the requirement to **REQUIRED** if you want the flow to | ||
| fail when no match is found or **ALTERNATIVE** (the authenticator will call `attempted()` when no | ||
| matching user is found, allowing the next step to run, if you fant to create a user if not found for example). |
| 4. Set the requirement to **REQUIRED** if you want the flow to | ||
| fail when no match is found or **ALTERNATIVE** (the authenticator will call `attempted()` when no | ||
| matching user is found, allowing the next step to run, if you fant to create a user if not found for example). |
Findeton
left a comment
There was a problem hiding this comment.
Approved but needs another pass.
Parent issue: https://github.com/sequentech/meta/issues/11932
idp-linking-authenticatorwith pom.xmlCustomAttributeIdpLinkingAuthenticatorextendingAbstractIdpAuthenticatorCustomAttributeIdpLinkingAuthenticatorFactorywith configurable parameterspom.xmlto include new moduleDockerfile.keycloakto copy new JARcustom-attribute-idp-linking-authenticator(42 chars) toidp-linking-authenticator(25 chars) — Keycloak'sAUTHENTICATION_EXECUTION.AUTHENTICATORcolumn ischaracter varying(36)