[KEYCLOAK-8273] - Failed to evaluate permissions when in permissive mode and using UMA tickets

This commit is contained in:
Pedro Igor 2018-09-11 20:08:39 -03:00
parent 609c521c17
commit 044d153c37
3 changed files with 67 additions and 36 deletions

View file

@ -160,12 +160,22 @@ public class DecisionPermissionCollector extends AbstractDecisionCollector {
metadata = request.getMetadata(); metadata = request.getMetadata();
} }
Permission permission;
if (resource != null) { if (resource != null) {
String resourceName = metadata == null || metadata.getIncludeResourceName() ? resource.getName() : null; String resourceName = metadata == null || metadata.getIncludeResourceName() ? resource.getName() : null;
return new Permission(resource.getId(), resourceName, scopes, claims); permission = new Permission(resource.getId(), resourceName, scopes, claims);
} else {
permission = new Permission(null, null, scopes, claims);
} }
return new Permission(null, null, scopes, claims); onGrant(permission);
return permission;
}
protected void onGrant(Permission permission) {
} }
private static boolean isResourcePermission(Policy policy) { private static boolean isResourcePermission(Policy policy) {

View file

@ -38,6 +38,7 @@ import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.representations.idm.authorization.AuthorizationRequest; import org.keycloak.representations.idm.authorization.AuthorizationRequest;
import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.representations.idm.authorization.PermissionTicketToken; import org.keycloak.representations.idm.authorization.PermissionTicketToken;
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
/** /**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@ -60,45 +61,27 @@ public class PermissionTicketAwareDecisionResultCollector extends DecisionPermis
} }
@Override @Override
public void onDecision(DefaultEvaluation evaluation) { protected void onGrant(Permission grantedPermission) {
super.onDecision(evaluation); // Removes permissions (represented by {@code ticket}) granted by any user-managed policy so we don't create unnecessary permission tickets.
removePermissionsIfGranted(evaluation); List<Permission> permissions = ticket.getPermissions();
} Iterator<Permission> itPermissions = permissions.iterator();
/** while (itPermissions.hasNext()) {
* Removes permissions (represented by {@code ticket}) granted by any user-managed policy so we don't create unnecessary permission tickets. Permission permission = itPermissions.next();
*
* @param evaluation the evaluation
*/
private void removePermissionsIfGranted(DefaultEvaluation evaluation) {
if (Effect.PERMIT.equals(evaluation.getEffect())) {
Policy policy = evaluation.getParentPolicy();
if ("uma".equals(policy.getType())) { if (permission.getResourceId() == null || permission.getResourceId().equals(grantedPermission.getResourceId())) {
ResourcePermission grantedPermission = evaluation.getPermission(); Set<String> scopes = permission.getScopes();
List<Permission> permissions = ticket.getPermissions(); Iterator<String> itScopes = scopes.iterator();
Iterator<Permission> itPermissions = permissions.iterator(); while (itScopes.hasNext()) {
if (grantedPermission.getScopes().contains(itScopes.next())) {
while (itPermissions.hasNext()) { itScopes.remove();
Permission permission = itPermissions.next();
if (permission.getResourceId().equals(grantedPermission.getResource().getId())) {
Set<String> scopes = permission.getScopes();
Iterator<String> itScopes = scopes.iterator();
while (itScopes.hasNext()) {
Scope scope = authorization.getStoreFactory().getScopeStore().findByName(itScopes.next(), resourceServer.getId());
if (policy.getScopes().contains(scope)) {
itScopes.remove();
}
}
if (scopes.isEmpty()) {
itPermissions.remove();
}
} }
} }
if (scopes.isEmpty()) {
itPermissions.remove();
}
} }
} }
} }

View file

@ -39,8 +39,10 @@ import org.keycloak.representations.idm.authorization.AuthorizationResponse;
import org.keycloak.representations.idm.authorization.JSPolicyRepresentation; import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.representations.idm.authorization.PermissionTicketRepresentation; import org.keycloak.representations.idm.authorization.PermissionTicketRepresentation;
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;
/** /**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@ -440,4 +442,40 @@ public class UserManagedAccessTest extends AbstractResourceServerTest {
assertEquals(1, permissionTickets.size()); assertEquals(1, permissionTickets.size());
} }
@Test
public void testPermissiveModePermissions() throws Exception {
resource = addResource("Resource A");
try {
authorize("kolo", "password", resource.getId(), null);
fail("Access should be denied, server in enforcing mode");
} catch (AuthorizationDeniedException ade) {
}
AuthorizationResource authorizationResource = getClient(getRealm()).authorization();
ResourceServerRepresentation settings = authorizationResource.getSettings();
settings.setPolicyEnforcementMode(PolicyEnforcementMode.PERMISSIVE);
authorizationResource.update(settings);
AuthorizationResponse response = authorize("marta", "password", "Resource A", null);
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 A");
assertTrue(permissions.isEmpty());
}
} }