KEYCLOAK-4998 Fix NPE in AttributeToRoleMapper

This commit is contained in:
Hynek Mlnarik 2017-12-08 01:19:57 +01:00 committed by Hynek Mlnařík
parent 464535ac81
commit 4a012b73ea
4 changed files with 114 additions and 20 deletions

View file

@ -127,7 +127,7 @@ public class AttributeToRoleMapper extends AbstractIdentityProviderMapper {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) { for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute(); AttributeType attr = choice.getAttribute();
if (name != null && !name.equals(attr.getName())) continue; if (name != null && !name.equals(attr.getName())) continue;
if (friendly != null && !name.equals(attr.getFriendlyName())) continue; if (friendly != null && !friendly.equals(attr.getFriendlyName())) continue;
for (Object val : attr.getAttributeValue()) { for (Object val : attr.getAttributeValue()) {
if (val.equals(desiredValue)) return true; if (val.equals(desiredValue)) return true;
} }

View file

@ -20,6 +20,7 @@ import org.openqa.selenium.TimeoutException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -34,10 +35,18 @@ import org.jboss.arquillian.graphene.page.Page;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import static org.keycloak.testsuite.broker.BrokerTestTools.*; import static org.keycloak.testsuite.broker.BrokerTestTools.*;
public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest { public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest {
public static final String ROLE_USER = "user";
public static final String ROLE_MANAGER = "manager";
public static final String ROLE_FRIENDLY_MANAGER = "friendly-manager";
protected IdentityProviderResource identityProviderResource; protected IdentityProviderResource identityProviderResource;
@Before @Before
@ -338,9 +347,12 @@ public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest {
} }
protected void createRolesForRealm(String realm) { protected void createRolesForRealm(String realm) {
RoleRepresentation managerRole = new RoleRepresentation("manager",null, false); RoleRepresentation managerRole = new RoleRepresentation(ROLE_MANAGER,null, false);
RoleRepresentation userRole = new RoleRepresentation("user",null, false); RoleRepresentation friendlyManagerRole = new RoleRepresentation(ROLE_FRIENDLY_MANAGER,null, false);
RoleRepresentation userRole = new RoleRepresentation(ROLE_USER,null, false);
adminClient.realm(realm).roles().create(managerRole); adminClient.realm(realm).roles().create(managerRole);
adminClient.realm(realm).roles().create(friendlyManagerRole);
adminClient.realm(realm).roles().create(userRole); adminClient.realm(realm).roles().create(userRole);
} }
@ -367,27 +379,32 @@ public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest {
createRoleMappersForConsumerRealm(); createRoleMappersForConsumerRealm();
RoleRepresentation managerRole = adminClient.realm(bc.providerRealmName()).roles().get("manager").toRepresentation(); RoleRepresentation managerRole = adminClient.realm(bc.providerRealmName()).roles().get(ROLE_MANAGER).toRepresentation();
RoleRepresentation userRole = adminClient.realm(bc.providerRealmName()).roles().get("user").toRepresentation(); RoleRepresentation userRole = adminClient.realm(bc.providerRealmName()).roles().get(ROLE_USER).toRepresentation();
UserResource userResource = adminClient.realm(bc.providerRealmName()).users().get(userId); UserResource userResource = adminClient.realm(bc.providerRealmName()).users().get(userId);
userResource.roles().realmLevel().add(Collections.singletonList(managerRole)); userResource.roles().realmLevel().add(Collections.singletonList(managerRole));
logInAsUserInIDPForFirstTime(); logInAsUserInIDPForFirstTime();
List<RoleRepresentation> currentRoles = userResource.roles().realmLevel().listAll(); Set<String> currentRoles = userResource.roles().realmLevel().listAll().stream()
assertEquals("There should be manager role",1, currentRoles.stream().filter(role -> role.getName().equals("manager")).collect(Collectors.toList()).size()); .map(RoleRepresentation::getName)
assertEquals("User shouldn't have user role", 0, currentRoles.stream().filter(role -> role.getName().equals("user")).collect(Collectors.toList()).size()); .collect(Collectors.toSet());
assertThat(currentRoles, hasItems(ROLE_MANAGER));
assertThat(currentRoles, not(hasItems(ROLE_USER)));
logoutFromRealm(bc.consumerRealmName()); logoutFromRealm(bc.consumerRealmName());
userResource.roles().realmLevel().add(Collections.singletonList(userRole)); userResource.roles().realmLevel().add(Collections.singletonList(userRole));
logInAsUserInIDP(); logInAsUserInIDP();
currentRoles = userResource.roles().realmLevel().listAll(); currentRoles = userResource.roles().realmLevel().listAll().stream()
assertEquals("There should be manager role",1, currentRoles.stream().filter(role -> role.getName().equals("manager")).collect(Collectors.toList()).size()); .map(RoleRepresentation::getName)
assertEquals("There should be user role",1, currentRoles.stream().filter(role -> role.getName().equals("user")).collect(Collectors.toList()).size()); .collect(Collectors.toSet());
assertThat(currentRoles, hasItems(ROLE_MANAGER, ROLE_USER));
logoutFromRealm(bc.providerRealmName()); logoutFromRealm(bc.providerRealmName());
logoutFromRealm(bc.consumerRealmName()); logoutFromRealm(bc.consumerRealmName());

View file

@ -18,16 +18,16 @@ public class KcOidcBrokerTest extends AbstractBrokerTest {
attrMapper1.setName("manager-role-mapper"); attrMapper1.setName("manager-role-mapper");
attrMapper1.setIdentityProviderMapper(ExternalKeycloakRoleToRoleMapper.PROVIDER_ID); attrMapper1.setIdentityProviderMapper(ExternalKeycloakRoleToRoleMapper.PROVIDER_ID);
attrMapper1.setConfig(ImmutableMap.<String,String>builder() attrMapper1.setConfig(ImmutableMap.<String,String>builder()
.put("external.role", "manager") .put("external.role", ROLE_MANAGER)
.put("role", "manager") .put("role", ROLE_MANAGER)
.build()); .build());
IdentityProviderMapperRepresentation attrMapper2 = new IdentityProviderMapperRepresentation(); IdentityProviderMapperRepresentation attrMapper2 = new IdentityProviderMapperRepresentation();
attrMapper2.setName("user-role-mapper"); attrMapper2.setName("user-role-mapper");
attrMapper2.setIdentityProviderMapper(ExternalKeycloakRoleToRoleMapper.PROVIDER_ID); attrMapper2.setIdentityProviderMapper(ExternalKeycloakRoleToRoleMapper.PROVIDER_ID);
attrMapper2.setConfig(ImmutableMap.<String,String>builder() attrMapper2.setConfig(ImmutableMap.<String,String>builder()
.put("external.role", "user") .put("external.role", ROLE_USER)
.put("role", "user") .put("role", ROLE_USER)
.build()); .build());
return Lists.newArrayList(attrMapper1, attrMapper2); return Lists.newArrayList(attrMapper1, attrMapper2);

View file

@ -1,15 +1,28 @@
package org.keycloak.testsuite.broker; package org.keycloak.testsuite.broker;
import org.keycloak.admin.client.resource.UserResource;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.keycloak.broker.saml.mappers.AttributeToRoleMapper; import org.keycloak.broker.saml.mappers.AttributeToRoleMapper;
import org.keycloak.broker.saml.mappers.UserAttributeMapper; import org.keycloak.broker.saml.mappers.UserAttributeMapper;
import org.keycloak.protocol.saml.SamlProtocol; import org.keycloak.protocol.saml.SamlProtocol;
import org.keycloak.representations.idm.IdentityProviderMapperRepresentation; import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.services.resources.RealmsResource; import org.keycloak.services.resources.RealmsResource;
import java.net.URI; import java.net.URI;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriBuilderException; import javax.ws.rs.core.UriBuilderException;
import org.junit.Test;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import static org.keycloak.testsuite.broker.AbstractBrokerTest.ROLE_FRIENDLY_MANAGER;
import static org.keycloak.testsuite.broker.AbstractBrokerTest.ROLE_MANAGER;
import static org.keycloak.testsuite.broker.AbstractBrokerTest.ROLE_USER;
public class KcSamlBrokerTest extends AbstractBrokerTest { public class KcSamlBrokerTest extends AbstractBrokerTest {
@ -25,8 +38,8 @@ public class KcSamlBrokerTest extends AbstractBrokerTest {
attrMapper1.setIdentityProviderMapper(AttributeToRoleMapper.PROVIDER_ID); attrMapper1.setIdentityProviderMapper(AttributeToRoleMapper.PROVIDER_ID);
attrMapper1.setConfig(ImmutableMap.<String,String>builder() attrMapper1.setConfig(ImmutableMap.<String,String>builder()
.put(UserAttributeMapper.ATTRIBUTE_NAME, "Role") .put(UserAttributeMapper.ATTRIBUTE_NAME, "Role")
.put(ATTRIBUTE_VALUE, "manager") .put(ATTRIBUTE_VALUE, ROLE_MANAGER)
.put("role", "manager") .put("role", ROLE_MANAGER)
.build()); .build());
IdentityProviderMapperRepresentation attrMapper2 = new IdentityProviderMapperRepresentation(); IdentityProviderMapperRepresentation attrMapper2 = new IdentityProviderMapperRepresentation();
@ -34,11 +47,75 @@ public class KcSamlBrokerTest extends AbstractBrokerTest {
attrMapper2.setIdentityProviderMapper(AttributeToRoleMapper.PROVIDER_ID); attrMapper2.setIdentityProviderMapper(AttributeToRoleMapper.PROVIDER_ID);
attrMapper2.setConfig(ImmutableMap.<String,String>builder() attrMapper2.setConfig(ImmutableMap.<String,String>builder()
.put(UserAttributeMapper.ATTRIBUTE_NAME, "Role") .put(UserAttributeMapper.ATTRIBUTE_NAME, "Role")
.put(ATTRIBUTE_VALUE, "user") .put(ATTRIBUTE_VALUE, ROLE_USER)
.put("role", "user") .put("role", ROLE_USER)
.build()); .build());
return Lists.newArrayList(attrMapper1, attrMapper2); IdentityProviderMapperRepresentation attrMapper3 = new IdentityProviderMapperRepresentation();
attrMapper3.setName("friendly-mapper");
attrMapper3.setIdentityProviderMapper(AttributeToRoleMapper.PROVIDER_ID);
attrMapper3.setConfig(ImmutableMap.<String,String>builder()
.put(UserAttributeMapper.ATTRIBUTE_FRIENDLY_NAME, AbstractUserAttributeMapperTest.ATTRIBUTE_TO_MAP_FRIENDLY_NAME)
.put(ATTRIBUTE_VALUE, ROLE_FRIENDLY_MANAGER)
.put("role", ROLE_FRIENDLY_MANAGER)
.build());
return Lists.newArrayList(attrMapper1, attrMapper2, attrMapper3);
}
// KEYCLOAK-3987
@Test
@Override
public void grantNewRoleFromToken() {
createRolesForRealm(bc.providerRealmName());
createRolesForRealm(bc.consumerRealmName());
createRoleMappersForConsumerRealm();
RoleRepresentation managerRole = adminClient.realm(bc.providerRealmName()).roles().get(ROLE_MANAGER).toRepresentation();
RoleRepresentation friendlyManagerRole = adminClient.realm(bc.providerRealmName()).roles().get(ROLE_FRIENDLY_MANAGER).toRepresentation();
RoleRepresentation userRole = adminClient.realm(bc.providerRealmName()).roles().get(ROLE_USER).toRepresentation();
UserResource userResource = adminClient.realm(bc.providerRealmName()).users().get(userId);
userResource.roles().realmLevel().add(Collections.singletonList(managerRole));
logInAsUserInIDPForFirstTime();
Set<String> currentRoles = userResource.roles().realmLevel().listAll().stream()
.map(RoleRepresentation::getName)
.collect(Collectors.toSet());
assertThat(currentRoles, hasItems(ROLE_MANAGER));
assertThat(currentRoles, not(hasItems(ROLE_USER, ROLE_FRIENDLY_MANAGER)));
logoutFromRealm(bc.consumerRealmName());
userResource.roles().realmLevel().add(Collections.singletonList(userRole));
userResource.roles().realmLevel().add(Collections.singletonList(friendlyManagerRole));
logInAsUserInIDP();
currentRoles = userResource.roles().realmLevel().listAll().stream()
.map(RoleRepresentation::getName)
.collect(Collectors.toSet());
assertThat(currentRoles, hasItems(ROLE_MANAGER, ROLE_USER, ROLE_FRIENDLY_MANAGER));
logoutFromRealm(bc.consumerRealmName());
userResource.roles().realmLevel().remove(Collections.singletonList(friendlyManagerRole));
logInAsUserInIDP();
currentRoles = userResource.roles().realmLevel().listAll().stream()
.map(RoleRepresentation::getName)
.collect(Collectors.toSet());
assertThat(currentRoles, hasItems(ROLE_MANAGER, ROLE_USER));
assertThat(currentRoles, not(hasItems(ROLE_FRIENDLY_MANAGER)));
logoutFromRealm(bc.providerRealmName());
logoutFromRealm(bc.consumerRealmName());
} }
protected URI getAuthServerSamlEndpoint(String realm) throws IllegalArgumentException, UriBuilderException { protected URI getAuthServerSamlEndpoint(String realm) throws IllegalArgumentException, UriBuilderException {