[KEYCLOAK-8445] - Owner not granted with permissions when using only scope-based permissions
This commit is contained in:
parent
7f1c03a122
commit
8e57cee30f
2 changed files with 99 additions and 8 deletions
|
@ -16,9 +16,30 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.authorization.policy.provider.permission;
|
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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class UMAPolicyProvider extends AbstractPermissionProvider {
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
|
||||||
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
@ -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<Permission> 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<PermissionTicketRepresentation> 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.
|
* 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);
|
assertNotNull(permissions);
|
||||||
assertPermissions(permissions, resource.getName(), "ScopeA", "ScopeB");
|
assertPermissions(permissions, resource.getName(), "ScopeA", "ScopeB");
|
||||||
assertTrue(permissions.isEmpty());
|
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
|
@Test
|
||||||
|
@ -364,7 +434,7 @@ public class UserManagedAccessTest extends AbstractResourceServerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUserGrantsAccessToScope() throws Exception {
|
public void testScopePermissionsToScopeOnly() throws Exception {
|
||||||
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
|
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
|
||||||
resource = addResource("Resource A", "marta", true, "ScopeA", "ScopeB");
|
resource = addResource("Resource A", "marta", true, "ScopeA", "ScopeB");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue