trigger IDENTITY_PROVIDER_FIRST_LOGIN (and UPDATE_PROFILE ) event when identity provider flow succeeds (#15100)
closes #15098
This commit is contained in:
parent
6d2e57f93a
commit
fb5a7f654b
4 changed files with 53 additions and 5 deletions
|
@ -107,7 +107,6 @@ public class IdpReviewProfileAuthenticator extends AbstractIdpAuthenticator {
|
|||
@Override
|
||||
protected void actionImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext userCtx, BrokeredIdentityContext brokerContext) {
|
||||
EventBuilder event = context.getEvent();
|
||||
//velias: looks like UPDATE_PROFILE event is not fired. IMHO it should not be fired here as user record in keycloak is not changed, user doesn't exist yet
|
||||
event.event(EventType.UPDATE_PROFILE).detail(Details.CONTEXT, UserProfileContext.IDP_REVIEW.name());
|
||||
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
|
||||
UserModelDelegate updatedProfile = new UserModelDelegate(null) {
|
||||
|
|
|
@ -773,6 +773,7 @@ public class LoginActionsService {
|
|||
|
||||
SessionCodeChecks checks = checksForCode(authSessionId, code, execution, clientId, tabId, flowPath);
|
||||
if (!checks.verifyActiveAndValidAction(AuthenticationSessionModel.Action.AUTHENTICATE.name(), ClientSessionCode.ActionType.LOGIN)) {
|
||||
event.error("Failed to verify login action");
|
||||
return checks.getResponse();
|
||||
}
|
||||
event.detail(Details.CODE_ID, code);
|
||||
|
@ -784,7 +785,9 @@ public class LoginActionsService {
|
|||
SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromAuthenticationSession(authSession, noteKey);
|
||||
if (serializedCtx == null) {
|
||||
ServicesLogger.LOGGER.notFoundSerializedCtxInClientSession(noteKey);
|
||||
throw new WebApplicationException(ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, "Not found serialized context in authenticationSession."));
|
||||
String message = "Not found serialized context in authenticationSession.";
|
||||
event.error(message);
|
||||
throw new WebApplicationException(ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, message));
|
||||
}
|
||||
BrokeredIdentityContext brokerContext = serializedCtx.deserialize(session, authSession);
|
||||
final String identityProviderAlias = brokerContext.getIdpConfig().getAlias();
|
||||
|
@ -792,17 +795,23 @@ public class LoginActionsService {
|
|||
String flowId = firstBrokerLogin ? brokerContext.getIdpConfig().getFirstBrokerLoginFlowId() : brokerContext.getIdpConfig().getPostBrokerLoginFlowId();
|
||||
if (flowId == null) {
|
||||
ServicesLogger.LOGGER.flowNotConfigForIDP(identityProviderAlias);
|
||||
throw new WebApplicationException(ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, "Flow not configured for identity provider"));
|
||||
String message = "Flow not configured for identity provider";
|
||||
event.error(message);
|
||||
throw new WebApplicationException(ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, message));
|
||||
}
|
||||
AuthenticationFlowModel brokerLoginFlow = realm.getAuthenticationFlowById(flowId);
|
||||
if (brokerLoginFlow == null) {
|
||||
ServicesLogger.LOGGER.flowNotFoundForIDP(flowId, identityProviderAlias);
|
||||
throw new WebApplicationException(ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, "Flow not found for identity provider"));
|
||||
String message = "Flow not found for identity provider";
|
||||
event.error(message);
|
||||
throw new WebApplicationException(ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, message));
|
||||
}
|
||||
|
||||
event.detail(Details.IDENTITY_PROVIDER, identityProviderAlias)
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, brokerContext.getUsername());
|
||||
|
||||
event.success();
|
||||
|
||||
AuthenticationProcessor processor = new AuthenticationProcessor() {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -45,6 +45,7 @@ import static org.junit.Assert.assertThat;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.testsuite.broker.BrokerRunOnServerUtil.assertHardCodedSessionNote;
|
||||
import static org.keycloak.testsuite.broker.BrokerRunOnServerUtil.configureAutoLinkFlow;
|
||||
import static org.keycloak.testsuite.broker.BrokerTestConstants.IDP_OIDC_ALIAS;
|
||||
import static org.keycloak.testsuite.broker.BrokerTestConstants.USER_EMAIL;
|
||||
import static org.keycloak.testsuite.broker.BrokerTestTools.getConsumerRoot;
|
||||
import static org.keycloak.testsuite.broker.BrokerTestTools.getProviderRoot;
|
||||
|
@ -1007,6 +1008,16 @@ public abstract class AbstractFirstBrokerLoginTest extends AbstractInitializedBa
|
|||
Assert.assertEquals("no-first-name", accountUpdateProfilePage.getUsername());
|
||||
|
||||
RealmRepresentation consumerRealmRep = adminClient.realm(bc.consumerRealmName()).toRepresentation();
|
||||
|
||||
events.expectAccount(EventType.IDENTITY_PROVIDER_FIRST_LOGIN).realm(consumerRealmRep).user((String)null)
|
||||
.detail(Details.IDENTITY_PROVIDER, bc.getIDPAlias())
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, "no-first-name")
|
||||
.assertEvent(getFirstConsumerEvent());
|
||||
|
||||
events.expectAccount(EventType.UPDATE_PROFILE).realm(consumerRealmRep).user((String)null)
|
||||
.detail(Details.CONTEXT, UserProfileContext.IDP_REVIEW.name())
|
||||
.assertEvent(getFirstConsumerEvent());
|
||||
|
||||
events.expectAccount(EventType.REGISTER).realm(consumerRealmRep).user(Matchers.any(String.class)).session((String) null)
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, "no-first-name")
|
||||
.detail(Details.REGISTER_METHOD, "broker")
|
||||
|
@ -1044,6 +1055,16 @@ public abstract class AbstractFirstBrokerLoginTest extends AbstractInitializedBa
|
|||
Assert.assertEquals("no-first-name", accountUpdateProfilePage.getUsername());
|
||||
|
||||
RealmRepresentation consumerRealmRep = adminClient.realm(bc.consumerRealmName()).toRepresentation();
|
||||
|
||||
events.expectAccount(EventType.IDENTITY_PROVIDER_FIRST_LOGIN).realm(consumerRealmRep).user((String)null)
|
||||
.detail(Details.IDENTITY_PROVIDER, bc.getIDPAlias())
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, "no-first-name")
|
||||
.assertEvent(getFirstConsumerEvent());
|
||||
|
||||
events.expectAccount(EventType.UPDATE_PROFILE).realm(consumerRealmRep).user((String)null)
|
||||
.detail(Details.CONTEXT, UserProfileContext.IDP_REVIEW.name())
|
||||
.assertEvent(getFirstConsumerEvent());
|
||||
|
||||
events.expectAccount(EventType.UPDATE_EMAIL).realm(consumerRealmRep).user((String)null).session((String) null)
|
||||
.detail(Details.CONTEXT, UserProfileContext.IDP_REVIEW.name())
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, "no-first-name")
|
||||
|
|
|
@ -27,6 +27,10 @@ import org.keycloak.events.Details;
|
|||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.userprofile.UserProfileContext;
|
||||
|
||||
import static org.keycloak.testsuite.AssertEvents.DEFAULT_USERNAME;
|
||||
import static org.keycloak.testsuite.broker.BrokerTestConstants.IDP_OIDC_ALIAS;
|
||||
|
||||
/**
|
||||
* Simple test to check the events after a broker login using OIDC. It also
|
||||
|
@ -68,6 +72,21 @@ public final class KcOidcBrokerEventTest extends AbstractBrokerTest {
|
|||
.client(bc.getIDPClientIdInProviderRealm())
|
||||
.assertEvent();
|
||||
|
||||
events.expect(EventType.IDENTITY_PROVIDER_FIRST_LOGIN)
|
||||
.realm(consumerRealm.toRepresentation().getId())
|
||||
.client("account")
|
||||
.user((String)null)
|
||||
.detail(Details.IDENTITY_PROVIDER, IDP_OIDC_ALIAS)
|
||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, bc.getUserLogin())
|
||||
.assertEvent();
|
||||
|
||||
events.expect(EventType.UPDATE_PROFILE)
|
||||
.realm(consumerRealm.toRepresentation().getId())
|
||||
.client("account")
|
||||
.user((String)null)
|
||||
.detail(Details.CONTEXT, UserProfileContext.IDP_REVIEW.name())
|
||||
.assertEvent();
|
||||
|
||||
events.expect(EventType.REGISTER)
|
||||
.realm(consumerRealm.toRepresentation().getId())
|
||||
.client("account")
|
||||
|
|
Loading…
Reference in a new issue