mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-25 16:42:34 +00:00
KEYCLOAK-1750 First broker login - events
This commit is contained in:
@@ -44,8 +44,7 @@ public interface Errors {
|
||||
|
||||
String NOT_ALLOWED = "not_allowed";
|
||||
|
||||
String FEDERATED_IDENTITY_EMAIL_EXISTS = "federated_identity_email_exists";
|
||||
String FEDERATED_IDENTITY_USERNAME_EXISTS = "federated_identity_username_exists";
|
||||
String FEDERATED_IDENTITY_EXISTS = "federated_identity_account_exists";
|
||||
String SSL_REQUIRED = "ssl_required";
|
||||
|
||||
String USER_SESSION_NOT_FOUND = "user_session_not_found";
|
||||
|
||||
@@ -48,6 +48,8 @@ public enum EventType {
|
||||
SEND_VERIFY_EMAIL_ERROR(true),
|
||||
SEND_RESET_PASSWORD(true),
|
||||
SEND_RESET_PASSWORD_ERROR(true),
|
||||
SEND_IDENTITY_PROVIDER_LINK(true),
|
||||
SEND_IDENTITY_PROVIDER_LINK_ERROR(true),
|
||||
RESET_PASSWORD(true),
|
||||
RESET_PASSWORD_ERROR(true),
|
||||
|
||||
@@ -66,8 +68,6 @@ public enum EventType {
|
||||
IDENTITY_PROVIDER_RESPONSE_ERROR(false),
|
||||
IDENTITY_PROVIDER_RETRIEVE_TOKEN(false),
|
||||
IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR(false),
|
||||
IDENTITY_PROVIDER_ACCCOUNT_LINKING(false),
|
||||
IDENTITY_PROVIDER_ACCCOUNT_LINKING_ERROR(false),
|
||||
IMPERSONATE(true),
|
||||
CUSTOM_REQUIRED_ACTION(true),
|
||||
CUSTOM_REQUIRED_ACTION_ERROR(true),
|
||||
|
||||
@@ -10,11 +10,12 @@ import org.keycloak.authentication.AuthenticationFlowContext;
|
||||
import org.keycloak.authentication.authenticators.broker.util.ExistingUserInfo;
|
||||
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
|
||||
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.FormMessage;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
|
||||
/**
|
||||
@@ -78,6 +79,15 @@ public class IdpCreateUserIfUniqueAuthenticator extends AbstractIdpAuthenticator
|
||||
.setError(Messages.FEDERATED_IDENTITY_EXISTS, duplication.getDuplicateAttributeName(), duplication.getDuplicateAttributeValue())
|
||||
.createErrorPage();
|
||||
context.challenge(challengeResponse);
|
||||
|
||||
if (context.getExecution().isRequired()) {
|
||||
context.getEvent()
|
||||
.user(duplication.getExistingUserId())
|
||||
.detail("existing_" + duplication.getDuplicateAttributeName(), duplication.getDuplicateAttributeValue())
|
||||
.removeDetail(Details.AUTH_METHOD)
|
||||
.removeDetail(Details.AUTH_TYPE)
|
||||
.error(Errors.FEDERATED_IDENTITY_EXISTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@ import org.keycloak.authentication.authenticators.broker.util.SerializedBrokered
|
||||
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||
import org.keycloak.email.EmailException;
|
||||
import org.keycloak.email.EmailProvider;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.login.LoginFormsProvider;
|
||||
import org.keycloak.models.ClientSessionModel;
|
||||
import org.keycloak.models.Constants;
|
||||
@@ -52,6 +56,15 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator
|
||||
String link = UriBuilder.fromUri(context.getActionUrl())
|
||||
.queryParam(Constants.KEY, clientSession.getNote(Constants.VERIFY_EMAIL_KEY))
|
||||
.build().toString();
|
||||
|
||||
EventBuilder event = context.getEvent().clone().event(EventType.SEND_IDENTITY_PROVIDER_LINK)
|
||||
.user(existingUser)
|
||||
.detail(Details.USERNAME, existingUser.getUsername())
|
||||
.detail(Details.EMAIL, existingUser.getEmail())
|
||||
.detail(Details.CODE_ID, clientSession.getId())
|
||||
.removeDetail(Details.AUTH_METHOD)
|
||||
.removeDetail(Details.AUTH_TYPE);
|
||||
|
||||
long expiration = TimeUnit.SECONDS.toMinutes(context.getRealm().getAccessCodeLifespanUserAction());
|
||||
try {
|
||||
|
||||
@@ -60,15 +73,11 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator
|
||||
.setUser(existingUser)
|
||||
.setAttribute(EmailProvider.IDENTITY_PROVIDER_BROKER_CONTEXT, brokerContext)
|
||||
.sendConfirmIdentityBrokerLink(link, expiration);
|
||||
// event.clone().event(EventType.SEND_RESET_PASSWORD)
|
||||
// .user(user)
|
||||
// .detail(Details.USERNAME, username)
|
||||
// .detail(Details.EMAIL, user.getEmail()).detail(Details.CODE_ID, context.getClientSession().getId()).success();
|
||||
|
||||
event.success();
|
||||
} catch (EmailException e) {
|
||||
// event.clone().event(EventType.SEND_RESET_PASSWORD)
|
||||
// .detail(Details.USERNAME, username)
|
||||
// .user(user)
|
||||
// .error(Errors.EMAIL_SEND_FAILED);
|
||||
event.error(Errors.EMAIL_SEND_FAILED);
|
||||
|
||||
logger.error("Failed to send email to confirm identity broker linking", e);
|
||||
Response challenge = context.form()
|
||||
.setError(Messages.EMAIL_SENT_ERROR)
|
||||
|
||||
@@ -724,7 +724,9 @@ public class AccountService extends AbstractSecuredLocalService {
|
||||
logger.debugv("Social provider {0} removed successfully from user {1}", providerId, user.getUsername());
|
||||
|
||||
event.event(EventType.REMOVE_FEDERATED_IDENTITY).client(auth.getClient()).user(auth.getUser())
|
||||
.detail(Details.USERNAME, link.getUserId() + "@" + link.getIdentityProvider())
|
||||
.detail(Details.USERNAME, auth.getUser().getUsername())
|
||||
.detail(Details.IDENTITY_PROVIDER, link.getIdentityProvider())
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, link.getUserName())
|
||||
.success();
|
||||
|
||||
setReferrerOnPage();
|
||||
|
||||
@@ -368,6 +368,13 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||
context.getUsername(), context.getToken());
|
||||
session.users().addFederatedIdentity(realmModel, federatedUser, federatedIdentityModel);
|
||||
|
||||
EventBuilder event = this.event.clone().user(federatedUser)
|
||||
.detail(Details.CODE_ID, clientSession.getId())
|
||||
.detail(Details.USERNAME, federatedUser.getUsername())
|
||||
.detail(Details.IDENTITY_PROVIDER, providerId)
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername())
|
||||
.removeDetail("auth_method");
|
||||
|
||||
String isRegisteredNewUser = clientSession.getNote(AbstractIdpAuthenticator.BROKER_REGISTERED_NEW_USER);
|
||||
if (Boolean.parseBoolean(isRegisteredNewUser)) {
|
||||
|
||||
@@ -388,15 +395,17 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||
federatedUser.setEmailVerified(true);
|
||||
}
|
||||
|
||||
this.event.clone().user(federatedUser).event(EventType.REGISTER)
|
||||
.detail(Details.IDENTITY_PROVIDER, providerId)
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername())
|
||||
.removeDetail("auth_method")
|
||||
event.event(EventType.REGISTER)
|
||||
.detail(Details.REGISTER_METHOD, "broker")
|
||||
.detail(Details.EMAIL, federatedUser.getEmail())
|
||||
.success();
|
||||
|
||||
} else {
|
||||
LOGGER.debugf("Linked existing keycloak user '%s' with identity provider '%s' . Identity provider username is '%s' .", federatedUser.getUsername(), providerId, context.getUsername());
|
||||
|
||||
event.event(EventType.FEDERATED_IDENTITY_LINK)
|
||||
.success();
|
||||
|
||||
updateFederatedIdentity(context, federatedUser);
|
||||
}
|
||||
|
||||
@@ -453,7 +462,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||
}
|
||||
|
||||
private Response performAccountLinking(ClientSessionModel clientSession, BrokeredIdentityContext context, FederatedIdentityModel federatedIdentityModel, UserModel federatedUser) {
|
||||
this.event.event(EventType.IDENTITY_PROVIDER_ACCCOUNT_LINKING);
|
||||
this.event.event(EventType.FEDERATED_IDENTITY_LINK);
|
||||
|
||||
if (federatedUser != null) {
|
||||
return redirectToErrorPage(Messages.IDENTITY_PROVIDER_ALREADY_LINKED, context.getIdpConfig().getAlias());
|
||||
@@ -478,7 +487,11 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||
this.session.users().addFederatedIdentity(this.realmModel, authenticatedUser, federatedIdentityModel);
|
||||
context.getIdp().attachUserSession(clientSession.getUserSession(), clientSession, context);
|
||||
|
||||
this.event.success();
|
||||
this.event.user(authenticatedUser)
|
||||
.detail(Details.USERNAME, authenticatedUser.getUsername())
|
||||
.detail(Details.IDENTITY_PROVIDER, federatedIdentityModel.getIdentityProvider())
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, federatedIdentityModel.getUserName())
|
||||
.success();
|
||||
return Response.status(302).location(UriBuilder.fromUri(clientSession.getRedirectUri()).build()).build();
|
||||
}
|
||||
|
||||
|
||||
@@ -509,6 +509,10 @@ public class LoginActionsService {
|
||||
BrokeredIdentityContext brokerContext = serializedCtx.deserialize(session, clientSession);
|
||||
AuthenticationFlowModel firstBrokerLoginFlow = realm.getAuthenticationFlowById(brokerContext.getIdpConfig().getFirstBrokerLoginFlowId());
|
||||
|
||||
event.detail(Details.IDENTITY_PROVIDER, brokerContext.getIdpConfig().getAlias())
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, brokerContext.getUsername());
|
||||
|
||||
|
||||
AuthenticationProcessor processor = new AuthenticationProcessor() {
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user