diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java index bbcaa57e85..b7be2cb291 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java @@ -38,7 +38,7 @@ import java.util.Map; * * @author Marek Posolda */ -public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, OIDCAccessTokenResponseMapper { +public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, OIDCAccessTokenResponseMapper, UserInfoTokenMapper { private static final List configProperties = new ArrayList<>(); @@ -102,6 +102,13 @@ public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements String userSessionNote, String tokenClaimName, String jsonType, boolean accessToken, boolean idToken) { + return createClaimMapper(name, userSessionNote, tokenClaimName, jsonType, accessToken, idToken, false); + } + + public static ProtocolMapperModel createClaimMapper(String name, + String userSessionNote, + String tokenClaimName, String jsonType, + boolean accessToken, boolean idToken, boolean userInfo) { ProtocolMapperModel mapper = new ProtocolMapperModel(); mapper.setName(name); mapper.setProtocolMapper(PROVIDER_ID); @@ -112,6 +119,7 @@ public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements config.put(OIDCAttributeMapperHelper.JSON_TYPE, jsonType); if (accessToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true"); if (idToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true"); + if (userInfo) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true"); mapper.setConfig(config); return mapper; } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/AbstractKerberosSingleRealmTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/AbstractKerberosSingleRealmTest.java index 3a5be0de2e..b48c7e6d44 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/AbstractKerberosSingleRealmTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/AbstractKerberosSingleRealmTest.java @@ -17,13 +17,10 @@ package org.keycloak.testsuite.federation.kerberos; -import java.net.URI; import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import javax.ws.rs.client.Entity; import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import org.ietf.jgss.GSSCredential; @@ -40,16 +37,16 @@ import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper; import org.keycloak.representations.AccessToken; +import org.keycloak.representations.UserInfo; import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.storage.UserStorageProvider; -import org.keycloak.testsuite.ActionURIUtils; import org.keycloak.testsuite.Assert; import org.keycloak.testsuite.admin.ApiUtil; import org.keycloak.testsuite.arquillian.annotation.DisableFeature; import org.keycloak.testsuite.pages.AppPage; -import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.util.AccountHelper; +import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.TestAppHelper; import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId; @@ -186,7 +183,7 @@ public abstract class AbstractKerberosSingleRealmTest extends AbstractKerberosTe ProtocolMapperModel protocolMapper = UserSessionNoteMapper.createClaimMapper(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME, KerberosConstants.GSS_DELEGATION_CREDENTIAL, KerberosConstants.GSS_DELEGATION_CREDENTIAL, "String", - true, false); + true, false, true); ProtocolMapperRepresentation protocolMapperRep = ModelToRepresentation.toRepresentation(protocolMapper); ClientResource clientResource = findClientByClientId(testRealmResource(), "kerberos-app"); Response response = clientResource.getProtocolMappers().createMapper(protocolMapperRep); @@ -194,7 +191,8 @@ public abstract class AbstractKerberosSingleRealmTest extends AbstractKerberosTe response.close(); // SPNEGO login - AccessToken token = assertSuccessfulSpnegoLogin("hnelson", "hnelson", "secret"); + OAuthClient.AccessTokenResponse tokenResponse = assertSuccessfulSpnegoLogin("hnelson", "hnelson", "secret"); + AccessToken token = oauth.verifyToken(tokenResponse.getAccessToken()); // Assert kerberos ticket in the accessToken can be re-used to authenticate against other 3rd party kerberos service (ApacheDS Server in this case) String serializedGssCredential = (String) token.getOtherClaims().get(KerberosConstants.GSS_DELEGATION_CREDENTIAL); @@ -203,6 +201,12 @@ public abstract class AbstractKerberosSingleRealmTest extends AbstractKerberosTe String ldapResponse = invokeLdap(gssCredential, token.getPreferredUsername()); Assert.assertEquals("Horatio Nelson", ldapResponse); + // Assert kerberos ticket also in userinfo endpoint + UserInfo userInfo = oauth.doUserInfoRequest(tokenResponse.getAccessToken()); + Assert.assertEquals(serializedGssCredential, userInfo.getOtherClaims().get(KerberosConstants.GSS_DELEGATION_CREDENTIAL)); + // Clear USER_INFO_REQUEST event + events.poll(); + // Logout oauth.openLogout(); events.poll(); @@ -211,8 +215,11 @@ public abstract class AbstractKerberosSingleRealmTest extends AbstractKerberosTe clientResource.getProtocolMappers().delete(protocolMapperId); // Login and assert delegated credential not anymore - token = assertSuccessfulSpnegoLogin("hnelson", "hnelson", "secret"); + tokenResponse = assertSuccessfulSpnegoLogin("hnelson", "hnelson", "secret"); + token = oauth.verifyToken(tokenResponse.getAccessToken()); Assert.assertFalse(token.getOtherClaims().containsKey(KerberosConstants.GSS_DELEGATION_CREDENTIAL)); + userInfo = oauth.doUserInfoRequest(tokenResponse.getAccessToken()); + Assert.assertFalse(userInfo.getOtherClaims().containsKey(KerberosConstants.GSS_DELEGATION_CREDENTIAL)); events.clear(); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/AbstractKerberosTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/AbstractKerberosTest.java index 30808992bb..5c40104278 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/AbstractKerberosTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/AbstractKerberosTest.java @@ -179,11 +179,11 @@ public abstract class AbstractKerberosTest extends AbstractAuthTest { // } - protected AccessToken assertSuccessfulSpnegoLogin(String loginUsername, String expectedUsername, String password) throws Exception { + protected OAuthClient.AccessTokenResponse assertSuccessfulSpnegoLogin(String loginUsername, String expectedUsername, String password) throws Exception { return assertSuccessfulSpnegoLogin("kerberos-app", loginUsername, expectedUsername, password); } - protected AccessToken assertSuccessfulSpnegoLogin(String clientId, String loginUsername, String expectedUsername, String password) throws Exception { + protected OAuthClient.AccessTokenResponse assertSuccessfulSpnegoLogin(String clientId, String loginUsername, String expectedUsername, String password) throws Exception { oauth.clientId(clientId); Response spnegoResponse = spnegoLogin(loginUsername, password); Assert.assertEquals(302, spnegoResponse.getStatus()); @@ -206,7 +206,7 @@ public abstract class AbstractKerberosTest extends AbstractAuthTest { oauth.idTokenHint(tokenResponse.getIdToken()); - return token; + return tokenResponse; } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/KerberosLdapCrossRealmTrustTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/KerberosLdapCrossRealmTrustTest.java index 17dee6eff5..bea9e63ea3 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/KerberosLdapCrossRealmTrustTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/kerberos/KerberosLdapCrossRealmTrustTest.java @@ -29,6 +29,7 @@ import org.keycloak.storage.ldap.kerberos.LDAPProviderKerberosConfig; import org.keycloak.testsuite.Assert; import org.keycloak.testsuite.util.KerberosRule; import org.keycloak.testsuite.KerberosEmbeddedServer; +import org.keycloak.testsuite.util.OAuthClient; import javax.ws.rs.core.Response; @@ -67,7 +68,8 @@ public class KerberosLdapCrossRealmTrustTest extends AbstractKerberosTest { @Test public void test01SpnegoLoginCRTSuccess() throws Exception { // Login as user from realm KC2.COM . Realm KEYCLOAK.ORG will trust us - AccessToken token = assertSuccessfulSpnegoLogin("hnelson2@KC2.COM", "hnelson2", "secret"); + OAuthClient.AccessTokenResponse tokenResponse = assertSuccessfulSpnegoLogin("hnelson2@KC2.COM", "hnelson2", "secret"); + AccessToken token = oauth.verifyToken(tokenResponse.getAccessToken()); Assert.assertEquals(token.getEmail(), "hnelson2@kc2.com"); assertUser("hnelson2", "hnelson2@kc2.com", "Horatio", "Nelson", false);