From d0b86d2f64ef443b9409faca26fd2cbf2daf4e53 Mon Sep 17 00:00:00 2001 From: Douglas Palmer Date: Fri, 24 Nov 2023 10:02:54 -0800 Subject: [PATCH] Register event not triggered on external to internal token exchange Closes #9684 Signed-off-by: Douglas Palmer --- .../oidc/DefaultTokenExchangeProvider.java | 15 +++++++++------ .../servlet/BrokerLinkAndTokenExchangeTest.java | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/services/src/main/java/org/keycloak/protocol/oidc/DefaultTokenExchangeProvider.java b/services/src/main/java/org/keycloak/protocol/oidc/DefaultTokenExchangeProvider.java index 89b51bc1b05..3f1b3d3158e 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/DefaultTokenExchangeProvider.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/DefaultTokenExchangeProvider.java @@ -33,6 +33,7 @@ import org.keycloak.common.util.Base64Url; import org.keycloak.events.Details; import org.keycloak.events.Errors; import org.keycloak.events.EventBuilder; +import org.keycloak.events.EventType; import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.JWSInputException; import org.keycloak.models.ClientModel; @@ -512,7 +513,6 @@ public class DefaultTokenExchangeProvider implements TokenExchangeProvider { // this must exist so that we can obtain access token from user session if idp's store tokens is off userSession.setNote(IdentityProvider.EXTERNAL_IDENTITY_PROVIDER, externalIdpModel.get().getAlias()); - userSession.setNote(IdentityProvider.FEDERATED_ACCESS_TOKEN, subjectToken); context.addSessionNotesToUserSession(userSession); @@ -524,11 +524,6 @@ public class DefaultTokenExchangeProvider implements TokenExchangeProvider { String providerId = identityProviderConfig.getAlias(); - // do we need this? - //AuthenticationSessionModel authenticationSession = clientCode.getClientSession(); - //context.setAuthenticationSession(authenticationSession); - //session.getContext().setClient(authenticationSession.getClient()); - context.getIdp().preprocessFederatedIdentity(session, realm, context); Set mappers = realm.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias()) .collect(Collectors.toSet()); @@ -604,6 +599,14 @@ public class DefaultTokenExchangeProvider implements TokenExchangeProvider { logger.debugf("Email verified automatically after registration of user '%s' through Identity provider '%s' ", user.getUsername(), context.getIdpConfig().getAlias()); user.setEmailVerified(true); } + + event.clone() + .event(EventType.REGISTER) + .user(user.getId()) + .detail(Details.REGISTER_METHOD, "token-exchange") + .detail(Details.EMAIL, user.getEmail()) + .detail(Details.IDENTITY_PROVIDER, providerId) + .success(); } else { if (!user.isEnabled()) { event.error(Errors.USER_DISABLED); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/BrokerLinkAndTokenExchangeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/BrokerLinkAndTokenExchangeTest.java index 7215d1e8148..cf2e7b87186 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/BrokerLinkAndTokenExchangeTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/BrokerLinkAndTokenExchangeTest.java @@ -24,6 +24,7 @@ import org.jboss.arquillian.test.api.ArquillianResource; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; import org.keycloak.admin.client.resource.ClientResource; @@ -33,6 +34,8 @@ import org.keycloak.authorization.model.ResourceServer; import org.keycloak.broker.oidc.OIDCIdentityProviderConfig; import org.keycloak.broker.oidc.mappers.UserAttributeMapper; import org.keycloak.common.Profile; +import org.keycloak.events.Details; +import org.keycloak.events.EventType; import org.keycloak.exportimport.ExportImportConfig; import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory; import org.keycloak.jose.jws.JWSInput; @@ -62,6 +65,7 @@ import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation import org.keycloak.representations.idm.authorization.DecisionStrategy; import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement; import org.keycloak.services.resources.admin.permissions.AdminPermissions; +import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest; import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; import org.keycloak.testsuite.arquillian.annotation.DisableFeature; @@ -148,6 +152,9 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest @Page private ClientApp appPage; + @Rule + public AssertEvents events = new AssertEvents(this); + @Override public void beforeAuthTest() { } @@ -157,6 +164,7 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest RealmRepresentation realm = new RealmRepresentation(); realm.setRealm(CHILD_IDP); realm.setEnabled(true); + realm.setEventsEnabled(true); ClientRepresentation servlet = new ClientRepresentation(); servlet.setClientId(ClientApp.DEPLOYMENT_NAME); servlet.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL); @@ -830,6 +838,12 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest UserRepresentation newUser = childRealm.users().search(PARENT3_USERNAME).get(0); Assert.assertNotNull(newUser.getAttributes()); Assert.assertTrue(newUser.getAttributes().containsKey("claim-to-broker")); + events.expect(EventType.REGISTER) + .realm(childRealm.toRepresentation()) + .client("exchange-linking") + .user(newUser) + .detail(Details.IDENTITY_PROVIDER, PARENT_IDP) + .assertEvent(childRealm.getEvents().get(1)); // cleanup remove the user childRealm.users().get(token.getSubject()).remove();