keycloak-uncached
Changes
server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultEvaluation.java 146(+146 -0)
server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Evaluation.java 7(+7 -0)
Details
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultEvaluation.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultEvaluation.java
index 74a2e07..cbf23cb 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultEvaluation.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultEvaluation.java
@@ -18,11 +18,26 @@
package org.keycloak.authorization.policy.evaluation;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.Decision;
import org.keycloak.authorization.Decision.Effect;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.permission.ResourcePermission;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.GroupModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RoleUtils;
import org.keycloak.representations.idm.authorization.Logic;
/**
@@ -36,6 +51,7 @@ public class DefaultEvaluation implements Evaluation {
private final Policy policy;
private final Policy parentPolicy;
private final AuthorizationProvider authorizationProvider;
+ private final Realm realm;
private Effect effect;
public DefaultEvaluation(ResourcePermission permission, EvaluationContext executionContext, Policy parentPolicy, Policy policy, Decision decision, AuthorizationProvider authorizationProvider) {
@@ -45,6 +61,7 @@ public class DefaultEvaluation implements Evaluation {
this.policy = policy;
this.decision = decision;
this.authorizationProvider = authorizationProvider;
+ this.realm = createRealm();
}
@Override
@@ -85,6 +102,11 @@ public class DefaultEvaluation implements Evaluation {
}
@Override
+ public Realm getRealm() {
+ return realm;
+ }
+
+ @Override
public AuthorizationProvider getAuthorizationProvider() {
return authorizationProvider;
}
@@ -102,4 +124,128 @@ public class DefaultEvaluation implements Evaluation {
deny();
}
}
+
+ private Realm createRealm() {
+ return new Realm() {
+
+ @Override
+ public boolean isUserInGroup(String id, String groupId, boolean checkParent) {
+ KeycloakSession session = authorizationProvider.getKeycloakSession();
+ UserModel user = getUser(id, session);
+
+ if (Objects.isNull(user)) {
+ return false;
+ }
+
+ RealmModel realm = session.getContext().getRealm();
+ GroupModel group = KeycloakModelUtils.findGroupByPath(realm, groupId);
+
+ if (Objects.isNull(group)) {
+ return false;
+ }
+
+ if (checkParent) {
+ return RoleUtils.isMember(user.getGroups(), group);
+ }
+
+ return user.isMemberOf(group);
+ }
+
+ private UserModel getUser(String id, KeycloakSession session) {
+ RealmModel realm = session.getContext().getRealm();
+ UserModel user = session.users().getUserById(id, realm);
+
+ if (Objects.isNull(user)) {
+ user = session.users().getUserByUsername(id, realm);
+
+ if (Objects.isNull(user)) {
+ user = session.users().getUserByEmail(id, realm);
+ }
+ }
+
+ return user;
+ }
+
+ @Override
+ public boolean isUserInRealmRole(String id, String roleName) {
+ KeycloakSession session = authorizationProvider.getKeycloakSession();
+ UserModel user = getUser(id, session);
+
+ if (Objects.isNull(user)) {
+ return false;
+ }
+
+ Set<RoleModel> roleMappings = user.getRoleMappings().stream()
+ .filter(role -> !role.isClientRole())
+ .collect(Collectors.toSet());
+
+ return RoleUtils.hasRole(roleMappings, session.getContext().getRealm().getRole(roleName));
+ }
+
+ @Override
+ public boolean isUserInClientRole(String id, String clientId, String roleName) {
+ KeycloakSession session = authorizationProvider.getKeycloakSession();
+ RealmModel realm = session.getContext().getRealm();
+ UserModel user = getUser(id, session);
+
+ if (Objects.isNull(user)) {
+ return false;
+ }
+
+ Set<RoleModel> roleMappings = user.getRoleMappings().stream()
+ .filter(role -> role.isClientRole() && ClientModel.class.cast(role.getContainer()).getClientId().equals(clientId))
+ .collect(Collectors.toSet());
+
+ if (roleMappings.isEmpty()) {
+ return false;
+ }
+
+ RoleModel role = realm.getClientById(ClientModel.class.cast(roleMappings.iterator().next().getContainer()).getId()).getRole(roleName);
+
+ if (Objects.isNull(role)) {
+ return false;
+ }
+
+ return RoleUtils.hasRole(roleMappings, role);
+ }
+
+ @Override
+ public boolean isGroupInRole(String id, String role) {
+ KeycloakSession session = authorizationProvider.getKeycloakSession();
+ RealmModel realm = session.getContext().getRealm();
+ GroupModel group = KeycloakModelUtils.findGroupByPath(realm, id);
+
+ return RoleUtils.hasRoleFromGroup(group, realm.getRole(role), false);
+ }
+
+ @Override
+ public List<String> getUserRealmRoles(String id) {
+ return getUser(id, authorizationProvider.getKeycloakSession()).getRoleMappings().stream()
+ .filter(role -> !role.isClientRole())
+ .map(RoleModel::getName)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List<String> getUserClientRoles(String id, String clientId) {
+ return getUser(id, authorizationProvider.getKeycloakSession()).getRoleMappings().stream()
+ .filter(role -> role.isClientRole())
+ .map(RoleModel::getName)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List<String> getUserGroups(String id) {
+ return getUser(id, authorizationProvider.getKeycloakSession()).getGroups().stream()
+ .map(ModelToRepresentation::buildGroupPath)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Map<String, List<String>> getUserAttributes(String id) {
+ Map<String, List<String>> attributes = getUser(id, authorizationProvider.getKeycloakSession()).getAttributes();
+ return attributes;
+ }
+ };
+ }
}
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Evaluation.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Evaluation.java
index 4ac0264..7fd6566 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Evaluation.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Evaluation.java
@@ -51,6 +51,13 @@ public interface Evaluation {
*/
Policy getPolicy();
+ /**
+ * Returns a {@link Realm} that can be used by policies to query information.
+ *
+ * @return a {@link Realm} instance
+ */
+ Realm getRealm();
+
AuthorizationProvider getAuthorizationProvider();
/**
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Realm.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Realm.java
new file mode 100644
index 0000000..b5d5dbb
--- /dev/null
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Realm.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2018 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.authorization.policy.evaluation;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This interface provides methods to query information from a realm.
+ *
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public interface Realm {
+
+ /**
+ * <p>Checks whether or not a user with the given <code>id</code> is a member of the given <code>group</code>.
+ *
+ * <p>This method will also consider memberships where the user is a member of any child group of the given <code>group</code>.
+ * For instance, if user is member of <code>/Group A/Group B</code> and this method is checking if user is a member of <code>/Group A</code>
+ * the result will be <code>true</code> given that the user is a member of a child group of <code>/Group A</code>.
+ *
+ * @param id the user id. It can be the id, username or email
+ * @param group the group path. For instance, /Group A/Group B.
+ * @return true if user is a member of the given group. Otherwise returns false.
+ */
+ default boolean isUserInGroup(String id, String group) {
+ return isUserInGroup(id, group, true);
+ }
+
+ /**
+ * Checks whether or not a user with the given <code>id</code> is a member of the given <code>group</code>.
+ *
+ * @param id the user id. It can be the id, username or email
+ * @param group the group path. For instance, /Group A/Group B.
+ * @param checkParent if true, this method returns true even though the user is not directly associated with the given group but a member of any child of the group.
+ * @return true if user is a member of the given group. Otherwise returns false.
+ */
+ boolean isUserInGroup(String id, String group, boolean checkParent);
+
+ /**
+ * Checks whether or not a user with the given <code>id</code> is granted with the given realm <code>role</code>.
+ *
+ * @param id the user id. It can be the id, username or email
+ * @param role the role name
+ * @return true if the user is granted with the role. Otherwise, false.
+ */
+ boolean isUserInRealmRole(String id, String role);
+
+ /**
+ * Checks whether or not a user with the given <code>id</code> is granted with the given client <code>role</code>.
+ *
+ * @param id the user id. It can be the id, username or email
+ * @param clientId the client id
+ * @param role the role name
+ * @return true if the user is granted with the role. Otherwise, false.
+ */
+ boolean isUserInClientRole(String id, String clientId, String role);
+
+ /**
+ * Checks whether or not a <code>group</code> is granted with the given realm <code>role</code>.
+ *
+ * @param group the group path. For instance, /Group A/Group B.
+ * @param role the role name
+ * @return true if the group is granted with the role. Otherwise, false.
+ */
+ boolean isGroupInRole(String group, String role);
+
+ /**
+ * Returns all realm roles granted for a user with the given <code>id</code>.
+ *
+ * @param id the user id. It can be the id, username or email
+ * @return the roles granted to the user
+ */
+ List<String> getUserRealmRoles(String id);
+
+ /**
+ * Returns all client roles granted for a user with the given <code>id</code>.
+ *
+ * @param id the user id. It can be the id, username or email
+ * @param clientId the client id
+ * @return the roles granted to the user
+ */
+ List<String> getUserClientRoles(String id, String clientId);
+
+ /**
+ * Returns all groups which the user with the given <code>id</code> is a member.
+ *
+ * @param id the user id. It can be the id, username or email
+ * @return the groups which the user is a member
+ */
+ List<String> getUserGroups(String id);
+
+ /**
+ * Returns all attributes associated with the a user with the given <code>id</code>.
+ *
+ * @param id the user id. It can be the id, username or email
+ * @return a map with the attributes associated with the user
+ */
+ Map<String, List<String>> getUserAttributes(String id);
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/PolicyEvaluationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/PolicyEvaluationTest.java
new file mode 100644
index 0000000..9ffad7b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/PolicyEvaluationTest.java
@@ -0,0 +1,578 @@
+/*
+ * Copyright 2018 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.authz;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+import org.junit.Test;
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.Decision;
+import org.keycloak.authorization.Decision.Effect;
+import org.keycloak.authorization.attribute.Attributes;
+import org.keycloak.authorization.common.DefaultEvaluationContext;
+import org.keycloak.authorization.identity.Identity;
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.permission.ResourcePermission;
+import org.keycloak.authorization.policy.evaluation.DefaultEvaluation;
+import org.keycloak.authorization.policy.evaluation.Evaluation;
+import org.keycloak.authorization.policy.provider.PolicyProvider;
+import org.keycloak.authorization.store.StoreFactory;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.mappers.GroupMembershipMapper;
+import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
+import org.keycloak.representations.idm.GroupRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
+import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
+import org.keycloak.testsuite.util.ClientBuilder;
+import org.keycloak.testsuite.util.GroupBuilder;
+import org.keycloak.testsuite.util.RealmBuilder;
+import org.keycloak.testsuite.util.RoleBuilder;
+import org.keycloak.testsuite.util.RolesBuilder;
+import org.keycloak.testsuite.util.UserBuilder;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class PolicyEvaluationTest extends AbstractAuthzTest {
+
+ @Override
+ public void addTestRealms(List<RealmRepresentation> testRealms) {
+ ProtocolMapperRepresentation groupProtocolMapper = new ProtocolMapperRepresentation();
+
+ groupProtocolMapper.setName("groups");
+ groupProtocolMapper.setProtocolMapper(GroupMembershipMapper.PROVIDER_ID);
+ groupProtocolMapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+ groupProtocolMapper.setConsentRequired(false);
+ Map<String, String> config = new HashMap<>();
+ config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "groups");
+ config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
+ config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
+ config.put("full.path", "true");
+ groupProtocolMapper.setConfig(config);
+
+ testRealms.add(RealmBuilder.create().name("authz-test")
+ .roles(RolesBuilder.create()
+ .realmRole(RoleBuilder.create().name("uma_authorization").build())
+ .realmRole(RoleBuilder.create().name("role-a").build())
+ .realmRole(RoleBuilder.create().name("role-b").build())
+ )
+ .group(GroupBuilder.create().name("Group A")
+ .subGroups(Arrays.asList("Group B", "Group D").stream().map(name -> {
+ if ("Group B".equals(name)) {
+ return GroupBuilder.create().name(name).subGroups(Arrays.asList("Group C", "Group E").stream().map(new Function<String, GroupRepresentation>() {
+ @Override
+ public GroupRepresentation apply(String name) {
+ return GroupBuilder.create().name(name).build();
+ }
+ }).collect(Collectors.toList())).build();
+ }
+ return GroupBuilder.create().name(name).realmRoles(Arrays.asList("role-a")).build();
+ }).collect(Collectors.toList())).build())
+ .group(GroupBuilder.create().name("Group E").build())
+ .user(UserBuilder.create().username("marta").password("password").addRoles("uma_authorization", "role-a").addGroups("Group A"))
+ .user(UserBuilder.create().username("alice").password("password").addRoles("uma_authorization").addGroups("/Group A/Group B/Group E"))
+ .user(UserBuilder.create().username("kolo").password("password").addRoles("uma_authorization").addGroups("/Group A/Group D"))
+ .user(UserBuilder.create().username("trinity").password("password").addRoles("uma_authorization").role("role-mapping-client", "client-role-a"))
+ .user(UserBuilder.create().username("jdoe").password("password").addGroups("/Group A/Group B", "/Group A/Group D"))
+ .client(ClientBuilder.create().clientId("resource-server-test")
+ .secret("secret")
+ .authorizationServicesEnabled(true)
+ .redirectUris("http://localhost/resource-server-test")
+ .defaultRoles("uma_protection")
+ .directAccessGrants()
+ .protocolMapper(groupProtocolMapper))
+ .client(ClientBuilder.create().clientId("role-mapping-client")
+ .defaultRoles("client-role-a", "client-role-b"))
+ .build());
+ }
+
+ @Deployment
+ public static WebArchive deploy() {
+ return RunOnServerDeployment.create(AbstractAuthzTest.class);
+ }
+
+ @Test
+ public void testCheckUserInGroup() {
+ testingClient.server().run(PolicyEvaluationTest::testCheckUserInGroup);
+ }
+
+ public static void testCheckUserInGroup(KeycloakSession session) {
+ session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
+ AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
+ ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
+ StoreFactory storeFactory = authorization.getStoreFactory();
+ ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
+ JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
+
+ policyRepresentation.setName("testCheckUserInGroup");
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInGroup('marta', 'Group C')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
+ PolicyProvider provider = authorization.getProvider(policy.getType());
+
+ DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertNull(evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInGroup('marta', 'Group A')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInGroup('marta', '/Group A')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInGroup('marta', '/Group A/Group B')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertNull(evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInGroup('alice', '/Group A/Group B/Group E')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInGroup('alice', '/Group A')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (!realm.isUserInGroup('alice', '/Group A', false)) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertNull(evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInGroup('alice', '/Group E')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertNull(evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInGroup('alice', 'Group E')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertNull(evaluation.getEffect());
+ }
+
+ @Test
+ public void testCheckUserInRole() {
+ testingClient.server().run(PolicyEvaluationTest::testCheckUserInRole);
+ }
+
+ public static void testCheckUserInRole(KeycloakSession session) {
+ session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
+ AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
+ ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
+ StoreFactory storeFactory = authorization.getStoreFactory();
+ ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
+ JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
+
+ policyRepresentation.setName("testCheckUserInRole");
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInRealmRole('marta', 'role-a')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
+ PolicyProvider provider = authorization.getProvider(policy.getType());
+
+ DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInRealmRole('marta', 'role-b')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertNull(evaluation.getEffect());
+ }
+
+ @Test
+ public void testCheckUserInClientRole() {
+ testingClient.server().run(PolicyEvaluationTest::testCheckUserInClientRole);
+ }
+
+ public static void testCheckUserInClientRole(KeycloakSession session) {
+ session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
+ AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
+ ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
+ StoreFactory storeFactory = authorization.getStoreFactory();
+ ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
+ JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
+
+ policyRepresentation.setName("testCheckUserInClientRole");
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInClientRole('trinity', 'role-mapping-client', 'client-role-a')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
+ PolicyProvider provider = authorization.getProvider(policy.getType());
+
+ DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isUserInRealmRole('trinity', 'client-role-b')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertNull(evaluation.getEffect());
+ }
+
+ @Test
+ public void testCheckGroupInRole() {
+ testingClient.server().run(PolicyEvaluationTest::testCheckGroupInRole);
+ }
+
+ public static void testCheckGroupInRole(KeycloakSession session) {
+ session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
+ AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
+ ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
+ StoreFactory storeFactory = authorization.getStoreFactory();
+ ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
+ JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
+
+ policyRepresentation.setName("testCheckGroupInRole");
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isGroupInRole('/Group A/Group D', 'role-a')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
+ PolicyProvider provider = authorization.getProvider(policy.getType());
+
+ DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+
+ builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("if (realm.isGroupInRole('/Group A/Group D', 'role-b')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ policyRepresentation.setId(policy.getId());
+ policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
+
+ evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertNull(evaluation.getEffect());
+ }
+
+ @Test
+ public void testCheckUserRealmRoles() {
+ testingClient.server().run(PolicyEvaluationTest::testCheckUserRealmRoles);
+ }
+
+ public static void testCheckUserRealmRoles(KeycloakSession session) {
+ session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
+ AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
+ ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
+ StoreFactory storeFactory = authorization.getStoreFactory();
+ ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
+ JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
+
+ policyRepresentation.setName("testCheckUserRealmRoles");
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("var roles = realm.getUserRealmRoles('marta');");
+ builder.append("if (roles.size() == 2 && roles.contains('uma_authorization') && roles.contains('role-a')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
+ PolicyProvider provider = authorization.getProvider(policy.getType());
+
+ DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+ }
+
+ @Test
+ public void testCheckUserClientRoles() {
+ testingClient.server().run(PolicyEvaluationTest::testCheckUserClientRoles);
+ }
+
+ public static void testCheckUserClientRoles(KeycloakSession session) {
+ session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
+ AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
+ ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
+ StoreFactory storeFactory = authorization.getStoreFactory();
+ ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
+ JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
+
+ policyRepresentation.setName("testCheckUserClientRoles");
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("var roles = realm.getUserClientRoles('trinity', 'role-mapping-client');");
+ builder.append("if (roles.size() == 1 && roles.contains('client-role-a')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
+ PolicyProvider provider = authorization.getProvider(policy.getType());
+
+ DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+ }
+
+ @Test
+ public void testCheckUserGroups() {
+ testingClient.server().run(PolicyEvaluationTest::testCheckUserGroups);
+ }
+
+ public static void testCheckUserGroups(KeycloakSession session) {
+ session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
+ AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
+ ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
+ StoreFactory storeFactory = authorization.getStoreFactory();
+ ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
+ JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
+
+ policyRepresentation.setName("testCheckUserGroups");
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("var groups = realm.getUserGroups('jdoe');");
+ builder.append("if (groups.size() == 2 && groups.contains('/Group A/Group B') && groups.contains('/Group A/Group D')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
+ PolicyProvider provider = authorization.getProvider(policy.getType());
+
+ DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+ }
+
+ @Test
+ public void testCheckUserAttributes() {
+ testingClient.server().run(PolicyEvaluationTest::testCheckUserAttributes);
+ }
+
+ public static void testCheckUserAttributes(KeycloakSession session) {
+ RealmModel realm = session.realms().getRealmByName("authz-test");
+ UserModel jdoe = session.users().getUserByUsername("jdoe", realm);
+
+ jdoe.setAttribute("a1", Arrays.asList("1", "2"));
+ jdoe.setSingleAttribute("a2", "3");
+
+ session.getContext().setRealm(realm);
+ AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
+ ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
+ StoreFactory storeFactory = authorization.getStoreFactory();
+ ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
+ JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
+
+ policyRepresentation.setName("testCheckUserAttributes");
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("var realm = $evaluation.getRealm();");
+ builder.append("var attributes = realm.getUserAttributes('jdoe');");
+ builder.append("if (attributes.size() == 2 && attributes.containsKey('a1') && attributes.containsKey('a2') && attributes.get('a1').size() == 2 && attributes.get('a2').get(0).equals('3')) { $evaluation.grant(); }");
+
+ policyRepresentation.setCode(builder.toString());
+
+ Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
+ PolicyProvider provider = authorization.getProvider(policy.getType());
+
+ DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
+
+ provider.evaluate(evaluation);
+
+ Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
+ }
+
+ @NotNull
+ private static DefaultEvaluation createEvaluation(KeycloakSession session, AuthorizationProvider authorization, ResourceServer resourceServer, Policy policy) {
+ return new DefaultEvaluation(new ResourcePermission(null, null, resourceServer), new DefaultEvaluationContext(new Identity() {
+ @Override
+ public String getId() {
+ return null;
+ }
+
+ @Override
+ public Attributes getAttributes() {
+ return null;
+ }
+ }, session), policy, policy, new Decision() {
+ @Override
+ public void onDecision(Evaluation evaluation) {
+
+ }
+ }, authorization);
+ }
+}