mirror of
https://github.com/keycloak/keycloak.git
synced 2026-04-26 08:58:59 -05:00
Move AbstractGroupTest.java, GroupMappersTest.java, GroupTest.java to the new testsuite
Part of: #34494 Signed-off-by: Simon Vacek <simonvacky@email.cz> # Conflicts: # test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmConfigBuilder.java # test-framework/core/src/main/java/org/keycloak/testframework/realm/UserConfigBuilder.java # Conflicts: # test-framework/core/src/main/java/org/keycloak/testframework/realm/ClientConfigBuilder.java
This commit is contained in:
committed by
Stian Thorgersen
parent
9e1d519e2c
commit
a8e33732cd
+14
@@ -1,6 +1,7 @@
|
||||
package org.keycloak.testframework.realm;
|
||||
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
@@ -69,6 +70,11 @@ public class ClientConfigBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClientConfigBuilder rootUrl(String rootUrl) {
|
||||
rep.setRootUrl(rootUrl);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClientConfigBuilder baseUrl(String baseUrl) {
|
||||
rep.setBaseUrl(baseUrl);
|
||||
return this;
|
||||
@@ -128,6 +134,14 @@ public class ClientConfigBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClientConfigBuilder protocolMappers(List<ProtocolMapperRepresentation> mappers) {
|
||||
if (rep.getProtocolMappers() == null) {
|
||||
rep.setProtocolMappers(new LinkedList<>());
|
||||
}
|
||||
rep.getProtocolMappers().addAll(mappers);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClientRepresentation build() {
|
||||
return rep;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package org.keycloak.testframework.realm;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class Collections {
|
||||
@@ -28,4 +30,25 @@ class Collections {
|
||||
return combine(l1, items.toList());
|
||||
}
|
||||
|
||||
static <K, V> Map<K, List<V>> combine(Map<K, List<V>> m1, Map<K, List<V>> m2) {
|
||||
if (m1 == null) {
|
||||
m1 = new HashMap<>();
|
||||
}
|
||||
for (Map.Entry<K, List<V>> entry : m2.entrySet()) {
|
||||
K k = entry.getKey();
|
||||
List<V> v = entry.getValue();
|
||||
m1.put(k, combine(m1.get(k), v));
|
||||
}
|
||||
return m1;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
static <K, V> Map<K, List<V>> combine(Map<K, List<V>> m1, K key, V... values) {
|
||||
return combine(m1, Map.of(key, List.of(values)));
|
||||
}
|
||||
|
||||
static <K, V> Map<K, List<V>> combine(Map<K, List<V>> m1, K key, Stream<V> values) {
|
||||
return combine(m1, Map.of(key, values.toList()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package org.keycloak.testframework.realm;
|
||||
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class GroupConfigBuilder {
|
||||
private final GroupRepresentation rep;
|
||||
|
||||
private GroupConfigBuilder(GroupRepresentation rep) {
|
||||
this.rep = rep;
|
||||
}
|
||||
|
||||
public static GroupConfigBuilder create() {
|
||||
GroupRepresentation rep = new GroupRepresentation();
|
||||
return new GroupConfigBuilder(rep);
|
||||
}
|
||||
|
||||
public static GroupConfigBuilder update(GroupRepresentation rep) {
|
||||
return new GroupConfigBuilder(rep);
|
||||
}
|
||||
|
||||
public GroupConfigBuilder name(String name) {
|
||||
rep.setName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GroupConfigBuilder path(String path) {
|
||||
rep.setPath(path);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GroupConfigBuilder realmRoles(String... realmRoles) {
|
||||
if (rep.getRealmRoles() == null) {
|
||||
rep.setRealmRoles(new LinkedList<>());
|
||||
}
|
||||
rep.getRealmRoles().addAll(List.of(realmRoles));
|
||||
return this;
|
||||
}
|
||||
|
||||
public GroupConfigBuilder clientRole(String client, String... clientRoles) {
|
||||
if (rep.getClientRoles() == null) {
|
||||
rep.setClientRoles(new HashMap<>());
|
||||
}
|
||||
rep.getClientRoles().put(client, List.of(clientRoles));
|
||||
return this;
|
||||
}
|
||||
|
||||
public GroupConfigBuilder attribute(String name, String... values) {
|
||||
rep.setAttributes(Collections.combine(rep.getAttributes(), name, values));
|
||||
return this;
|
||||
}
|
||||
|
||||
public GroupConfigBuilder setAttributes(Map<String, List<String>> attributes) {
|
||||
rep.setAttributes(attributes);
|
||||
return this;
|
||||
}
|
||||
//
|
||||
// public GroupConfigBuilder singleAttribute(String name, String value) {
|
||||
// rep.singleAttribute(name, value);
|
||||
// return this;
|
||||
// }
|
||||
|
||||
public GroupConfigBuilder subGroups(GroupRepresentation... subGroups) {
|
||||
if (rep.getSubGroups() == null) {
|
||||
rep.setSubGroups(new LinkedList<>());
|
||||
}
|
||||
rep.getSubGroups().addAll(List.of(subGroups));
|
||||
return this;
|
||||
}
|
||||
|
||||
public GroupRepresentation build() {
|
||||
return rep;
|
||||
}
|
||||
}
|
||||
+31
-1
@@ -1,6 +1,7 @@
|
||||
package org.keycloak.testframework.realm;
|
||||
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RolesRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
@@ -59,6 +60,15 @@ public class RealmConfigBuilder {
|
||||
return UserConfigBuilder.update(user).enabled(true).username(username);
|
||||
}
|
||||
|
||||
public GroupConfigBuilder addGroup(String name) {
|
||||
if (rep.getGroups() == null) {
|
||||
rep.setGroups(new LinkedList<>());
|
||||
}
|
||||
GroupRepresentation group = new GroupRepresentation();
|
||||
rep.getGroups().add(group);
|
||||
return GroupConfigBuilder.update(group).name(name);
|
||||
}
|
||||
|
||||
public RealmConfigBuilder registrationEmailAsUsername(boolean registrationEmailAsUsername) {
|
||||
rep.setRegistrationEmailAsUsername(registrationEmailAsUsername);
|
||||
return this;
|
||||
@@ -129,7 +139,22 @@ public class RealmConfigBuilder {
|
||||
if (rep.getRoles() == null) {
|
||||
rep.setRoles(new RolesRepresentation());
|
||||
}
|
||||
rep.getRoles().setRealm(Collections.combine(rep.getRoles().getRealm(), Arrays.stream(roleNames).map(Representations::toRole)));
|
||||
rep.getRoles().setRealm(Collections.combine(
|
||||
rep.getRoles().getRealm(),
|
||||
Arrays.stream(roleNames).map(r -> Representations.toRole(r, false))
|
||||
));
|
||||
return this;
|
||||
}
|
||||
|
||||
public RealmConfigBuilder clientRoles(String client, String... roleNames) {
|
||||
if (rep.getRoles() == null) {
|
||||
rep.setRoles(new RolesRepresentation());
|
||||
}
|
||||
rep.getRoles().setClient(Collections.combine(
|
||||
rep.getRoles().getClient(),
|
||||
client,
|
||||
Arrays.stream(roleNames).map(r -> Representations.toRole(r, true))
|
||||
));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -138,6 +163,11 @@ public class RealmConfigBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public RealmConfigBuilder defaultGroups(String... defaultGroupsNames) {
|
||||
rep.setDefaultGroups(Collections.combine(rep.getDefaultGroups(), defaultGroupsNames));
|
||||
return this;
|
||||
}
|
||||
|
||||
public RealmConfigBuilder internationalizationEnabled(boolean enabled) {
|
||||
rep.setInternationalizationEnabled(enabled);
|
||||
return this;
|
||||
|
||||
+2
-1
@@ -9,9 +9,10 @@ class Representations {
|
||||
private Representations() {
|
||||
}
|
||||
|
||||
static RoleRepresentation toRole(String roleName) {
|
||||
static RoleRepresentation toRole(String roleName, boolean clientRole) {
|
||||
RoleRepresentation role = new RoleRepresentation();
|
||||
role.setName(roleName);
|
||||
role.setClientRole(clientRole);
|
||||
return role;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -82,8 +82,8 @@ public class UserConfigBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserConfigBuilder attribute(String key, String value) {
|
||||
rep.singleAttribute(key, value);
|
||||
public UserConfigBuilder attribute(String name, String... value) {
|
||||
rep.setAttributes(Collections.combine(rep.getAttributes(), name, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,116 +15,68 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.admin.group;
|
||||
package org.keycloak.tests.admin.group;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.junit.Rule;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.admin.OperationType;
|
||||
import org.keycloak.events.admin.ResourceType;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.RefreshToken;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.util.AdminEventPaths;
|
||||
import org.keycloak.testsuite.util.AssertAdminEvents;
|
||||
import org.keycloak.testsuite.util.KeyUtils;
|
||||
import org.keycloak.testframework.annotations.InjectAdminEvents;
|
||||
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.testframework.events.AdminEventAssertion;
|
||||
import org.keycloak.testframework.events.AdminEvents;
|
||||
import org.keycloak.testframework.oauth.OAuthClient;
|
||||
import org.keycloak.testframework.oauth.annotations.InjectOAuthClient;
|
||||
import org.keycloak.testframework.realm.ManagedRealm;
|
||||
import org.keycloak.tests.utils.admin.AdminEventPaths;
|
||||
import org.keycloak.tests.utils.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm;
|
||||
import static org.keycloak.testsuite.util.ServerURLs.getAuthServerContextRoot;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public abstract class AbstractGroupTest extends AbstractKeycloakTest {
|
||||
@KeycloakIntegrationTest
|
||||
public abstract class AbstractGroupTest {
|
||||
|
||||
protected String testRealmId;
|
||||
@InjectAdminEvents
|
||||
AdminEvents adminEvents;
|
||||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(this);
|
||||
@InjectOAuthClient
|
||||
OAuthClient oAuth;
|
||||
|
||||
@Rule
|
||||
public AssertAdminEvents assertAdminEvents = new AssertAdminEvents(this);
|
||||
|
||||
@Override
|
||||
public void beforeAbstractKeycloakTest() throws Exception {
|
||||
super.beforeAbstractKeycloakTest();
|
||||
this.testRealmId = adminClient.realm(TEST).toRepresentation().getId();
|
||||
AccessToken login(String username, String clientId, String clientSecret) {
|
||||
AccessTokenResponse tokenResponse = oAuth.client(clientId, clientSecret).doPasswordGrantRequest(username, "password");
|
||||
return oAuth.parseToken(tokenResponse.getAccessToken(), AccessToken.class);
|
||||
}
|
||||
|
||||
AccessToken login(String login, String clientId, String clientSecret, String userId) throws Exception {
|
||||
AccessTokenResponse tokenResponse = oauth.client(clientId, clientSecret).doPasswordGrantRequest( login, "password");
|
||||
String createGroup(ManagedRealm managedRealm, GroupRepresentation group) {
|
||||
Response response = managedRealm.admin().groups().add(group);
|
||||
String groupId = ApiUtil.getCreatedId(response);
|
||||
managedRealm.cleanup().add(r -> r.groups().group(groupId).remove());
|
||||
AdminEventAssertion.assertEvent(adminEvents.poll(), OperationType.CREATE, AdminEventPaths.groupPath(groupId), group, ResourceType.GROUP);
|
||||
|
||||
String accessToken = tokenResponse.getAccessToken();
|
||||
String refreshToken = tokenResponse.getRefreshToken();
|
||||
|
||||
PublicKey publicKey = PemUtils.decodePublicKey(KeyUtils.findActiveSigningKey(adminClient.realm("test")).getPublicKey());
|
||||
|
||||
AccessToken accessTokenRepresentation = RSATokenVerifier.verifyToken(accessToken, publicKey, getAuthServerContextRoot() + "/auth/realms/test");
|
||||
|
||||
JWSInput jws = new JWSInput(refreshToken);
|
||||
RefreshToken refreshTokenRepresentation = jws.readJsonContent(RefreshToken.class);
|
||||
|
||||
events.expectLogin()
|
||||
.client(clientId)
|
||||
.user(userId)
|
||||
.detail(Details.GRANT_TYPE, OAuth2Constants.PASSWORD)
|
||||
.detail(Details.TOKEN_ID, accessTokenRepresentation.getId())
|
||||
.detail(Details.REFRESH_TOKEN_ID, refreshTokenRepresentation.getId())
|
||||
.detail(Details.USERNAME, login)
|
||||
.removeDetail(Details.CODE_ID)
|
||||
.removeDetail(Details.REDIRECT_URI)
|
||||
.removeDetail(Details.CONSENT)
|
||||
.assertEvent();
|
||||
|
||||
return accessTokenRepresentation;
|
||||
// Set ID to the original rep
|
||||
group.setId(groupId);
|
||||
return groupId;
|
||||
}
|
||||
|
||||
RealmRepresentation loadTestRealm(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation result = loadRealm("/testrealm.json");
|
||||
testRealms.add(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GroupRepresentation createGroup(RealmResource realm, GroupRepresentation group) {
|
||||
try (Response response = realm.groups().add(group)) {
|
||||
String groupId = ApiUtil.getCreatedId(response);
|
||||
getCleanup().addGroupId(groupId);
|
||||
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.groupPath(groupId), group, ResourceType.GROUP);
|
||||
|
||||
// Set ID to the original rep
|
||||
group.setId(groupId);
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
||||
void addSubGroup(RealmResource realm, GroupRepresentation parent, GroupRepresentation child) {
|
||||
Response response = realm.groups().add(child);
|
||||
child.setId(ApiUtil.getCreatedId(response));
|
||||
response = realm.groups().group(parent.getId()).subGroup(child);
|
||||
void addSubGroup(ManagedRealm managedRealm, GroupRepresentation parent, GroupRepresentation child) {
|
||||
Response response = managedRealm.admin().groups().add(child);
|
||||
adminEvents.skip();
|
||||
String childUuid = ApiUtil.getCreatedId(response);
|
||||
child.setId(childUuid);
|
||||
response = managedRealm.admin().groups().group(parent.getId()).subGroup(child);
|
||||
adminEvents.skip();
|
||||
response.close();
|
||||
}
|
||||
|
||||
RoleRepresentation createRealmRole(RealmResource realm, RoleRepresentation role) {
|
||||
realm.roles().create(role);
|
||||
|
||||
RoleRepresentation created = realm.roles().get(role.getName()).toRepresentation();
|
||||
getCleanup().addRoleId(created.getId());
|
||||
RoleRepresentation createRealmRole(ManagedRealm managedRealm, RoleRepresentation role) {
|
||||
managedRealm.admin().roles().create(role);
|
||||
RoleRepresentation created = managedRealm.admin().roles().get(role.getName()).toRepresentation();
|
||||
String createdName = created.getName();
|
||||
managedRealm.cleanup().add(r -> r.roles().deleteRole(createdName));
|
||||
return created;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.admin.group;
|
||||
package org.keycloak.tests.admin.group;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import java.util.*;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.ProtocolMappersResource;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.models.GroupProvider;
|
||||
@@ -34,143 +34,200 @@ import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
|
||||
import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testframework.annotations.InjectRealm;
|
||||
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.testframework.realm.GroupConfigBuilder;
|
||||
import org.keycloak.testframework.realm.ManagedRealm;
|
||||
import org.keycloak.testframework.realm.RealmConfig;
|
||||
import org.keycloak.testframework.realm.RealmConfigBuilder;
|
||||
import org.keycloak.tests.utils.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.util.ProtocolMapperUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@KeycloakIntegrationTest
|
||||
public class GroupMappersTest extends AbstractGroupTest {
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation testRealmRep = loadTestRealm(testRealms);
|
||||
@InjectRealm(config = GroupMappersTestRealmConfig.class)
|
||||
ManagedRealm managedRealm;
|
||||
|
||||
testRealmRep.setEventsEnabled(true);
|
||||
private static final String CLIENT_ID = "my-app";
|
||||
private static final String CLIENT_SECRET = "password";
|
||||
private static final String CLIENT_ROLE = "customer-user";
|
||||
private static final String TOP_GROUP = "topGroup";
|
||||
private static final String TOP_ATTRIBUTE = "topAttribute";
|
||||
private static final String LEVEL_2_ATTRIBUTE = "level2Attribute";
|
||||
private static final String LEVEL_2_GROUP = "level2group";
|
||||
private static final String TOP_GROUP_USER = "topGroupUser";
|
||||
private static final String LEVEL_2_GROUP_USER = "level2GroupUser";
|
||||
|
||||
ClientRepresentation client = getClientByAlias(testRealmRep, "test-app");
|
||||
Assert.assertNotNull("test-app client exists", client);
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testGroupMappers() {
|
||||
{
|
||||
UserRepresentation user = ApiUtil.findUserByUsername(managedRealm.admin(), TOP_GROUP_USER);
|
||||
|
||||
client.setDirectAccessGrantsEnabled(true);
|
||||
|
||||
List<ProtocolMapperRepresentation> mappers = new LinkedList<>();
|
||||
ProtocolMapperRepresentation mapper = new ProtocolMapperRepresentation();
|
||||
mapper.setName("groups");
|
||||
mapper.setProtocolMapper(GroupMembershipMapper.PROVIDER_ID);
|
||||
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
Map<String, String> config = new HashMap<>();
|
||||
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "groups.groups");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
mapper.setConfig(config);
|
||||
mappers.add(mapper);
|
||||
|
||||
mapper = new ProtocolMapperRepresentation();
|
||||
mapper.setName("topAttribute");
|
||||
mapper.setProtocolMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
config = new HashMap<>();
|
||||
config.put(ProtocolMapperUtils.USER_ATTRIBUTE, "topAttribute");
|
||||
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "topAttribute");
|
||||
config.put(OIDCAttributeMapperHelper.JSON_TYPE, ProviderConfigProperty.STRING_TYPE);
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
mapper.setConfig(config);
|
||||
mappers.add(mapper);
|
||||
|
||||
mapper = new ProtocolMapperRepresentation();
|
||||
mapper.setName("level2Attribute");
|
||||
mapper.setProtocolMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
config = new HashMap<>();
|
||||
config.put(ProtocolMapperUtils.USER_ATTRIBUTE, "level2Attribute");
|
||||
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "level2Attribute");
|
||||
config.put(OIDCAttributeMapperHelper.JSON_TYPE, ProviderConfigProperty.STRING_TYPE);
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
mapper.setConfig(config);
|
||||
mappers.add(mapper);
|
||||
|
||||
client.setProtocolMappers(mappers);
|
||||
}
|
||||
|
||||
private ClientRepresentation getClientByAlias(RealmRepresentation testRealmRep, String alias) {
|
||||
for (ClientRepresentation client: testRealmRep.getClients()) {
|
||||
if (alias.equals(client.getClientId())) {
|
||||
return client;
|
||||
}
|
||||
AccessToken token = login(user.getUsername(), CLIENT_ID, CLIENT_SECRET);
|
||||
Assertions.assertTrue(token.getRealmAccess().getRoles().contains("user"));
|
||||
Assertions.assertNotNull(token.getOtherClaims().get("groups"));
|
||||
Map<String, Collection<String>> groups = (Map<String, Collection<String>>) token.getOtherClaims().get("groups");
|
||||
MatcherAssert.assertThat(groups.get("groups"), Matchers.contains(TOP_GROUP));
|
||||
Assertions.assertEquals("true", token.getOtherClaims().get(TOP_ATTRIBUTE));
|
||||
}
|
||||
{
|
||||
UserRepresentation user = ApiUtil.findUserByUsername(managedRealm.admin(), LEVEL_2_GROUP_USER);
|
||||
|
||||
AccessToken token = login(user.getUsername(), CLIENT_ID, CLIENT_SECRET);
|
||||
Assertions.assertTrue(token.getRealmAccess().getRoles().contains("user"));
|
||||
Assertions.assertTrue(token.getRealmAccess().getRoles().contains("admin"));
|
||||
Assertions.assertTrue(token.getResourceAccess(CLIENT_ID).getRoles().contains(CLIENT_ROLE));
|
||||
Assertions.assertNotNull(token.getOtherClaims().get("groups"));
|
||||
Map<String, Collection<String>> groups = (Map<String, Collection<String>>) token.getOtherClaims().get("groups");
|
||||
MatcherAssert.assertThat(groups.get("groups"), Matchers.contains(LEVEL_2_GROUP));
|
||||
Assertions.assertEquals("true", token.getOtherClaims().get(TOP_ATTRIBUTE));
|
||||
Assertions.assertEquals("true", token.getOtherClaims().get(LEVEL_2_ATTRIBUTE));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testGroupMappers() throws Exception {
|
||||
RealmResource realm = adminClient.realms().realm("test");
|
||||
{
|
||||
UserRepresentation user = realm.users().search("topGroupUser", -1, -1).get(0);
|
||||
|
||||
AccessToken token = login(user.getUsername(), "test-app", "password", user.getId());
|
||||
Assert.assertTrue(token.getRealmAccess().getRoles().contains("user"));
|
||||
Assert.assertNotNull(token.getOtherClaims().get("groups"));
|
||||
Map<String, Collection<String>> groups = (Map<String, Collection<String>>) token.getOtherClaims().get("groups");
|
||||
MatcherAssert.assertThat(groups.get("groups"), Matchers.contains("topGroup"));
|
||||
Assert.assertEquals("true", token.getOtherClaims().get("topAttribute"));
|
||||
}
|
||||
{
|
||||
UserRepresentation user = realm.users().search("level2GroupUser", -1, -1).get(0);
|
||||
|
||||
AccessToken token = login(user.getUsername(), "test-app", "password", user.getId());
|
||||
Assert.assertTrue(token.getRealmAccess().getRoles().contains("user"));
|
||||
Assert.assertTrue(token.getRealmAccess().getRoles().contains("admin"));
|
||||
Assert.assertTrue(token.getResourceAccess("test-app").getRoles().contains("customer-user"));
|
||||
Assert.assertNotNull(token.getOtherClaims().get("groups"));
|
||||
Map<String, Collection<String>> groups = (Map<String, Collection<String>>) token.getOtherClaims().get("groups");
|
||||
MatcherAssert.assertThat(groups.get("groups"), Matchers.contains("level2group"));
|
||||
Assert.assertEquals("true", token.getOtherClaims().get("topAttribute"));
|
||||
Assert.assertEquals("true", token.getOtherClaims().get("level2Attribute"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupMappersWithSlash() throws Exception {
|
||||
RealmResource realm = adminClient.realms().realm("test");
|
||||
GroupRepresentation topGroup = realm.getGroupByPath("/topGroup");
|
||||
Assert.assertNotNull(topGroup);
|
||||
public void testGroupMappersWithSlash() {
|
||||
RealmResource realm = managedRealm.admin();
|
||||
GroupRepresentation topGroup = realm.getGroupByPath("/" + TOP_GROUP);
|
||||
Assertions.assertNotNull(topGroup);
|
||||
GroupRepresentation childSlash = new GroupRepresentation();
|
||||
childSlash.setName("child/slash");
|
||||
try (Response response = realm.groups().group(topGroup.getId()).subGroup(childSlash)) {
|
||||
Assert.assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
|
||||
childSlash.setId(ApiUtil.getCreatedId(response));
|
||||
}
|
||||
List<UserRepresentation> users = realm.users().search("level2GroupUser", true);
|
||||
Assert.assertEquals(1, users.size());
|
||||
UserRepresentation user = users.iterator().next();
|
||||
Response response = realm.groups().group(topGroup.getId()).subGroup(childSlash);
|
||||
childSlash.setId(ApiUtil.getCreatedId(response));
|
||||
|
||||
UserRepresentation user = ApiUtil.findUserByUsername(managedRealm.admin(), LEVEL_2_GROUP_USER);
|
||||
realm.users().get(user.getId()).joinGroup(childSlash.getId());
|
||||
|
||||
ProtocolMappersResource protocolMappers = ApiUtil.findClientResourceByClientId(realm, "test-app").getProtocolMappers();
|
||||
ClientResource client = ApiUtil.findClientByClientId(realm, CLIENT_ID);
|
||||
ProtocolMappersResource protocolMappers = client.getProtocolMappers();
|
||||
ProtocolMapperRepresentation groupsMapper = ProtocolMapperUtil.getMapperByNameAndProtocol(
|
||||
protocolMappers, OIDCLoginProtocol.LOGIN_PROTOCOL, "groups");
|
||||
Assertions.assertNotNull(groupsMapper);
|
||||
groupsMapper.getConfig().put("full.path", Boolean.TRUE.toString());
|
||||
protocolMappers.update(groupsMapper.getId(), groupsMapper);
|
||||
|
||||
try {
|
||||
AccessToken token = login(user.getUsername(), "test-app", "password", user.getId());
|
||||
Assert.assertNotNull(token.getOtherClaims().get("groups"));
|
||||
Map<String, Collection<String>> groups = (Map<String, Collection<String>>) token.getOtherClaims().get("groups");
|
||||
MatcherAssert.assertThat(groups.get("groups"), Matchers.containsInAnyOrder(
|
||||
KeycloakModelUtils.buildGroupPath(GroupProvider.DEFAULT_ESCAPE_SLASHES, "topGroup", "level2group"),
|
||||
KeycloakModelUtils.buildGroupPath(GroupProvider.DEFAULT_ESCAPE_SLASHES, "topGroup", "child/slash")));
|
||||
} finally {
|
||||
realm.users().get(user.getId()).leaveGroup(childSlash.getId());
|
||||
realm.groups().group(childSlash.getId()).remove();
|
||||
groupsMapper.getConfig().remove("full.path");
|
||||
protocolMappers.update(groupsMapper.getId(), groupsMapper);
|
||||
groupsMapper.getConfig().remove("full.path");
|
||||
managedRealm.cleanup().add(r -> {
|
||||
r.users().get(user.getId()).leaveGroup(childSlash.getId());
|
||||
r.groups().group(childSlash.getId()).remove();
|
||||
r.clients().get(client.toRepresentation().getId())
|
||||
.getProtocolMappers().update(groupsMapper.getId(), groupsMapper);
|
||||
});
|
||||
|
||||
AccessToken token = login(user.getUsername(), CLIENT_ID, CLIENT_SECRET);
|
||||
Assertions.assertNotNull(token.getOtherClaims().get("groups"));
|
||||
Map<String, Collection<String>> groups = (Map<String, Collection<String>>) token.getOtherClaims().get("groups");
|
||||
MatcherAssert.assertThat(groups.get("groups"), Matchers.containsInAnyOrder(
|
||||
KeycloakModelUtils.buildGroupPath(GroupProvider.DEFAULT_ESCAPE_SLASHES, TOP_GROUP, LEVEL_2_GROUP),
|
||||
KeycloakModelUtils.buildGroupPath(GroupProvider.DEFAULT_ESCAPE_SLASHES, TOP_GROUP, "child/slash")));
|
||||
}
|
||||
|
||||
private static class GroupMappersTestRealmConfig implements RealmConfig {
|
||||
|
||||
private List<ProtocolMapperRepresentation> createMappers() {
|
||||
List<ProtocolMapperRepresentation> mappers = new LinkedList<>();
|
||||
ProtocolMapperRepresentation mapper = new ProtocolMapperRepresentation();
|
||||
mapper.setName("groups");
|
||||
mapper.setProtocolMapper(GroupMembershipMapper.PROVIDER_ID);
|
||||
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
Map<String, String> config = new HashMap<>();
|
||||
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "groups.groups");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
mapper.setConfig(config);
|
||||
mappers.add(mapper);
|
||||
|
||||
mapper = new ProtocolMapperRepresentation();
|
||||
mapper.setName(TOP_ATTRIBUTE);
|
||||
mapper.setProtocolMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
config = new HashMap<>();
|
||||
config.put(ProtocolMapperUtils.USER_ATTRIBUTE, TOP_ATTRIBUTE);
|
||||
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, TOP_ATTRIBUTE);
|
||||
config.put(OIDCAttributeMapperHelper.JSON_TYPE, ProviderConfigProperty.STRING_TYPE);
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
mapper.setConfig(config);
|
||||
mappers.add(mapper);
|
||||
|
||||
mapper = new ProtocolMapperRepresentation();
|
||||
mapper.setName(LEVEL_2_ATTRIBUTE);
|
||||
mapper.setProtocolMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
config = new HashMap<>();
|
||||
config.put(ProtocolMapperUtils.USER_ATTRIBUTE, LEVEL_2_ATTRIBUTE);
|
||||
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, LEVEL_2_ATTRIBUTE);
|
||||
config.put(OIDCAttributeMapperHelper.JSON_TYPE, ProviderConfigProperty.STRING_TYPE);
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
mapper.setConfig(config);
|
||||
mappers.add(mapper);
|
||||
return mappers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmConfigBuilder configure(RealmConfigBuilder realm) {
|
||||
List<ProtocolMapperRepresentation> mappers = createMappers();
|
||||
|
||||
realm.addClient(CLIENT_ID)
|
||||
.enabled(true)
|
||||
.secret(CLIENT_SECRET)
|
||||
.directAccessGrants()
|
||||
.protocolMappers(mappers);
|
||||
|
||||
realm.eventsEnabled(true)
|
||||
.clientRoles(CLIENT_ID, CLIENT_ROLE);
|
||||
|
||||
GroupRepresentation subGroup = GroupConfigBuilder.create()
|
||||
.name(LEVEL_2_GROUP)
|
||||
.realmRoles("admin")
|
||||
.clientRole(CLIENT_ID, CLIENT_ROLE)
|
||||
.attribute(LEVEL_2_ATTRIBUTE, "true")
|
||||
.build();
|
||||
|
||||
|
||||
GroupRepresentation subGroup2 = GroupConfigBuilder.create()
|
||||
.name("level2group2")
|
||||
.realmRoles("admin")
|
||||
.clientRole(CLIENT_ID, CLIENT_ROLE)
|
||||
.attribute(LEVEL_2_ATTRIBUTE, "true")
|
||||
.build();
|
||||
|
||||
realm.addGroup(TOP_GROUP)
|
||||
.attribute(TOP_ATTRIBUTE, "true")
|
||||
.realmRoles("user")
|
||||
.subGroups(subGroup, subGroup2);
|
||||
|
||||
realm.addUser(TOP_GROUP_USER)
|
||||
.name("John", "Doe")
|
||||
.enabled(true)
|
||||
.email("top@redhat.com")
|
||||
.password("password")
|
||||
.groups(TOP_GROUP);
|
||||
|
||||
realm.addUser(LEVEL_2_GROUP_USER)
|
||||
.name("Jane", "Doe")
|
||||
.enabled(true)
|
||||
.email("level2@redhat.com")
|
||||
.password("password")
|
||||
.groups("topGroup/level2group");
|
||||
|
||||
return realm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user