diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/permission/UMAPolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/permission/UMAPolicyProvider.java
index 50f6993637..a1a60c79da 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/permission/UMAPolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/permission/UMAPolicyProvider.java
@@ -16,9 +16,30 @@
*/
package org.keycloak.authorization.policy.provider.permission;
+import org.keycloak.authorization.identity.Identity;
+import org.keycloak.authorization.model.Resource;
+import org.keycloak.authorization.permission.ResourcePermission;
+import org.keycloak.authorization.policy.evaluation.Evaluation;
+
/**
* @author Pedro Igor
*/
public class UMAPolicyProvider extends AbstractPermissionProvider {
+ @Override
+ public void evaluate(Evaluation evaluation) {
+ ResourcePermission permission = evaluation.getPermission();
+ Resource resource = permission.getResource();
+
+ if (resource != null) {
+ Identity identity = evaluation.getContext().getIdentity();
+
+ // no need to evaluate UMA permissions to resource owner resources
+ if (resource.getOwner().equals(identity.getId())) {
+ return;
+ }
+ }
+
+ super.evaluate(evaluation);
+ }
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/UserManagedAccessTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/UserManagedAccessTest.java
index 2d7a69a2c7..1b6b9a35b7 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/UserManagedAccessTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/UserManagedAccessTest.java
@@ -43,6 +43,7 @@ import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
+import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation;
/**
* @author Pedro Igor
@@ -101,6 +102,82 @@ public class UserManagedAccessTest extends AbstractResourceServerTest {
}
}
+ @Test
+ public void testOnlyOwnerCanAccessPermissionsToScope() throws Exception {
+ resource = addResource("Resource A", "marta", true, "ScopeA", "ScopeB");
+ ScopePermissionRepresentation permission = new ScopePermissionRepresentation();
+
+ permission.setName(resource.getName() + " Scope A Permission");
+ permission.addScope("ScopeA");
+ permission.addPolicy("Only Owner Policy");
+
+ getClient(getRealm()).authorization().permissions().scope().create(permission).close();
+
+ permission = new ScopePermissionRepresentation();
+
+ permission.setName(resource.getName() + " Scope B Permission");
+ permission.addScope("ScopeB");
+ permission.addPolicy("Only Owner Policy");
+
+ getClient(getRealm()).authorization().permissions().scope().create(permission).close();
+
+ AuthorizationResponse response = authorize("marta", "password", resource.getName(), new String[] {"ScopeA", "ScopeB"});
+ String rpt = response.getToken();
+
+ assertNotNull(rpt);
+ assertFalse(response.isUpgraded());
+
+ AccessToken accessToken = toAccessToken(rpt);
+ AccessToken.Authorization authorization = accessToken.getAuthorization();
+
+ assertNotNull(authorization);
+
+ Collection permissions = authorization.getPermissions();
+
+ assertNotNull(permissions);
+ assertPermissions(permissions, resource.getName(), "ScopeA", "ScopeB");
+ assertTrue(permissions.isEmpty());
+
+ try {
+ response = authorize("kolo", "password", resource.getId(), new String[] {"ScopeA", "ScopeB"});
+ fail("User should not have access to resource from another user");
+ } catch (AuthorizationDeniedException ade) {
+ }
+
+ List tickets = getAuthzClient().protection().permission().find(resource.getId(), null, null, null, null, null, null, null);
+
+ for (PermissionTicketRepresentation ticket : tickets) {
+ ticket.setGranted(true);
+ getAuthzClient().protection().permission().update(ticket);
+ }
+
+ try {
+ response = authorize("kolo", "password", resource.getId(), new String[] {"ScopeA", "ScopeB"});
+ } catch (AuthorizationDeniedException ade) {
+ fail("User should have access to resource from another user");
+ }
+
+ rpt = response.getToken();
+ accessToken = toAccessToken(rpt);
+ authorization = accessToken.getAuthorization();
+ permissions = authorization.getPermissions();
+ assertPermissions(permissions, resource.getName(), "ScopeA", "ScopeB");
+ assertTrue(permissions.isEmpty());
+
+ try {
+ response = authorize("marta", "password", resource.getId(), new String[] {"ScopeB"});
+ } catch (AuthorizationDeniedException ade) {
+ fail("User should have access to his own resources");
+ }
+
+ rpt = response.getToken();
+ accessToken = toAccessToken(rpt);
+ authorization = accessToken.getAuthorization();
+ permissions = authorization.getPermissions();
+ assertPermissions(permissions, resource.getName(), "ScopeB");
+ assertTrue(permissions.isEmpty());
+ }
+
/**
* Makes sure permissions granted to a typed resource instance does not grant access to resource instances with the same type.
*
@@ -176,13 +253,6 @@ public class UserManagedAccessTest extends AbstractResourceServerTest {
assertNotNull(permissions);
assertPermissions(permissions, resource.getName(), "ScopeA", "ScopeB");
assertTrue(permissions.isEmpty());
-
- try {
- response = authorize("kolo", "password", resourceB.getId(), new String[] {"ScopeA", "ScopeB"});
- fail("User should not have access to resource from another user");
- } catch (AuthorizationDeniedException ade) {
-
- }
}
@Test
@@ -364,7 +434,7 @@ public class UserManagedAccessTest extends AbstractResourceServerTest {
}
@Test
- public void testUserGrantsAccessToScope() throws Exception {
+ public void testScopePermissionsToScopeOnly() throws Exception {
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
resource = addResource("Resource A", "marta", true, "ScopeA", "ScopeB");