Use dedicated error message when user is already linked to idp

Closes #45322

Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
This commit is contained in:
Stefan Guilhen
2026-01-09 15:30:29 -03:00
committed by Pedro Igor
parent 99a46155ca
commit e22016db7f
3 changed files with 20 additions and 6 deletions
@@ -177,6 +177,8 @@ public class Messages {
public static final String IDENTITY_PROVIDER_ALREADY_LINKED = "identityProviderAlreadyLinkedMessage";
public static final String IDENTITY_PROVIDER_ALREADY_LINKED_TO_CURRENT_USER = "identityProviderAlreadyLinkedToCurrentUserMessage";
public static final String INSUFFICIENT_PERMISSION = "insufficientPermissionMessage";
public static final String COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST = "couldNotProceedWithAuthenticationRequestMessage";
@@ -87,6 +87,7 @@ import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.IdentityProviderSyncMode;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
@@ -749,10 +750,14 @@ public class IdentityBrokerService implements UserAuthenticationIdentityProvider
FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(context.getIdpConfig().getAlias(), context.getId(),
context.getUsername(), context.getToken());
session.users().addFederatedIdentity(realmModel, federatedUser, federatedIdentityModel);
try {
session.users().addFederatedIdentity(realmModel, federatedUser, federatedIdentityModel);
} catch (ModelDuplicateException de) {
String idpDisplayName = KeycloakModelUtils.getIdentityProviderDisplayName(session, context.getIdpConfig());
return redirectToErrorPage(authSession, Status.CONFLICT, Messages.IDENTITY_PROVIDER_ALREADY_LINKED_TO_CURRENT_USER, de, idpDisplayName);
}
}
String isRegisteredNewUser = authSession.getAuthNote(BROKER_REGISTERED_NEW_USER);
if (Boolean.parseBoolean(isRegisteredNewUser)) {
@@ -785,7 +790,6 @@ public class IdentityBrokerService implements UserAuthenticationIdentityProvider
}
return finishOrRedirectToPostBrokerLogin(authSession, context, true);
} catch (Exception e) {
return redirectToErrorPage(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR, e);
}
@@ -1027,8 +1031,15 @@ public class IdentityBrokerService implements UserAuthenticationIdentityProvider
}
}
} else {
this.session.users().addFederatedIdentity(this.realmModel, authenticatedUser, newModel);
federatedUser = authenticatedUser;
try {
this.session.users().addFederatedIdentity(this.realmModel, authenticatedUser, newModel);
federatedUser = authenticatedUser;
} catch(ModelDuplicateException e) {
logger.warnf(e,"Cannot link user '%s' to identity provider '%s' as the link already exists for this user and identity provider",
authenticatedUser.getUsername(), context.getIdpConfig().getAlias());
String idpDisplayName = KeycloakModelUtils.getIdentityProviderDisplayName(session, context.getIdpConfig());
return redirectToErrorWhenLinkingFailed(authSession, Messages.IDENTITY_PROVIDER_ALREADY_LINKED_TO_CURRENT_USER, idpDisplayName);
}
}
updateFederatedIdentity(context, federatedUser);
@@ -373,6 +373,8 @@ identityProviderInvalidResponseMessage=Invalid response from identity provider.
identityProviderInvalidSignatureMessage=Invalid signature in response from identity provider.
identityProviderNotFoundMessage=Could not find an identity provider with the identifier.
identityProviderLinkSuccess=You successfully verified your email. Please go back to your original browser and continue there with the login.
identityProviderAlreadyLinkedMessage=Federated identity returned by {0} is already linked to another user.
identityProviderAlreadyLinkedToCurrentUserMessage=Your account is already linked to the identity provider {0}.
staleCodeMessage=This page is no longer valid, please go back to your application and sign in again
realmSupportsNoCredentialsMessage=Realm does not support any credential type.
credentialSetupRequired=Cannot login, credential setup required.
@@ -383,7 +385,6 @@ emailVerifiedAlreadyMessageHeader=Email address verified
emailVerifiedAlreadyMessage=Your email address has been verified already.
staleEmailVerificationLink=The link you clicked is an old stale link and is no longer valid. Maybe you have already verified your email.
emailVerificationCancelled=This email verification has been cancelled by an administrator.
identityProviderAlreadyLinkedMessage=Federated identity returned by {0} is already linked to another user.
confirmAccountLinking=Confirm linking the account {0} of identity provider {1} with your account.
confirmAccountLinkingBody=If you link the account, you will also be able to login using account {0} of the identity provider {1}. Do not proceed if you did not initiate this process or you do not want to link the account.
confirmEmailAddressVerificationHeader=Email address validation