[KEYCLOAK-16515] - Scope permissions not added to result if previous permission is granted
This commit is contained in:
parent
10294f4e2b
commit
c631013031
3 changed files with 80 additions and 6 deletions
|
@ -31,6 +31,7 @@ import org.keycloak.representations.idm.authorization.Permission;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -44,7 +45,7 @@ public class DecisionPermissionCollector extends AbstractDecisionCollector {
|
|||
private final AuthorizationProvider authorizationProvider;
|
||||
private final ResourceServer resourceServer;
|
||||
private final AuthorizationRequest request;
|
||||
private final List<Permission> permissions = new ArrayList<>();
|
||||
private final Set<Permission> permissions = new LinkedHashSet<>();
|
||||
|
||||
public DecisionPermissionCollector(AuthorizationProvider authorizationProvider, ResourceServer resourceServer, AuthorizationRequest request) {
|
||||
this.authorizationProvider = authorizationProvider;
|
||||
|
@ -181,7 +182,7 @@ public class DecisionPermissionCollector extends AbstractDecisionCollector {
|
|||
throw new RuntimeException("Failed to evaluate permissions", cause);
|
||||
}
|
||||
|
||||
protected void grantPermission(AuthorizationProvider authorizationProvider, List<Permission> permissions, ResourcePermission permission, Collection<Scope> grantedScopes, ResourceServer resourceServer, AuthorizationRequest request, Result result) {
|
||||
protected void grantPermission(AuthorizationProvider authorizationProvider, Set<Permission> permissions, ResourcePermission permission, Collection<Scope> grantedScopes, ResourceServer resourceServer, AuthorizationRequest request, Result result) {
|
||||
Set<String> scopeNames = grantedScopes.stream().map(Scope::getName).collect(Collectors.toSet());
|
||||
Resource resource = permission.getResource();
|
||||
|
||||
|
@ -192,11 +193,9 @@ public class DecisionPermissionCollector extends AbstractDecisionCollector {
|
|||
|
||||
resourceStore.findByScope(grantedScopes.stream().map(Scope::getId).collect(Collectors.toList()), resourceServer.getId(), resource1 -> permissions.add(createPermission(resource, scopeNames, permission.getClaims(), request)));
|
||||
|
||||
if (permissions.isEmpty()) {
|
||||
permissions.add(createPermission(null, scopeNames, permission.getClaims(), request));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Permission createPermission(Resource resource, Set<String> scopes, Map<String, Set<String>> claims, AuthorizationRequest request) {
|
||||
AuthorizationRequest.Metadata metadata = null;
|
||||
|
|
|
@ -324,7 +324,7 @@ public class PolicyEvaluationService {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void grantPermission(AuthorizationProvider authorizationProvider, List<Permission> permissions, ResourcePermission permission, Collection<Scope> grantedScopes, ResourceServer resourceServer, AuthorizationRequest request, Result result) {
|
||||
protected void grantPermission(AuthorizationProvider authorizationProvider, Set<Permission> permissions, ResourcePermission permission, Collection<Scope> grantedScopes, ResourceServer resourceServer, AuthorizationRequest request, Result result) {
|
||||
result.setStatus(Effect.PERMIT);
|
||||
result.getPermission().getScopes().retainAll(grantedScopes);
|
||||
super.grantPermission(authorizationProvider, permissions, permission, grantedScopes, resourceServer, request, result);
|
||||
|
|
|
@ -2296,6 +2296,81 @@ public class EntitlementAPITest extends AbstractAuthzTest {
|
|||
assertNull(response.getRefreshToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPermissionOrder() throws Exception {
|
||||
ClientResource client = getClient(getRealm(), RESOURCE_SERVER_TEST);
|
||||
AuthorizationResource authorization = client.authorization();
|
||||
JSPolicyRepresentation policy = new JSPolicyRepresentation();
|
||||
|
||||
policy.setName(KeycloakModelUtils.generateId());
|
||||
policy.setCode("$evaluation.grant();");
|
||||
|
||||
authorization.policies().js().create(policy).close();
|
||||
|
||||
ResourceRepresentation resource = new ResourceRepresentation();
|
||||
|
||||
resource.setName("my_resource");
|
||||
resource.addScope("entity:read");
|
||||
|
||||
try (Response response = authorization.resources().create(resource)) {
|
||||
resource = response.readEntity(ResourceRepresentation.class);
|
||||
}
|
||||
|
||||
ScopeRepresentation featureAccessScope = new ScopeRepresentation("feature:access");
|
||||
authorization.scopes().create(featureAccessScope);
|
||||
|
||||
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
|
||||
|
||||
permission.setName(KeycloakModelUtils.generateId());
|
||||
permission.addPolicy(policy.getName());
|
||||
permission.addResource(resource.getId());
|
||||
|
||||
authorization.permissions().resource().create(permission).close();
|
||||
|
||||
ScopePermissionRepresentation scopePermission = new ScopePermissionRepresentation();
|
||||
|
||||
scopePermission.setName(KeycloakModelUtils.generateId());
|
||||
scopePermission.addPolicy(policy.getName());
|
||||
scopePermission.addScope(featureAccessScope.getName());
|
||||
|
||||
authorization.permissions().scope().create(scopePermission).close();
|
||||
|
||||
AuthorizationRequest request = new AuthorizationRequest();
|
||||
|
||||
request.addPermission(null, "entity:read");
|
||||
request.addPermission(null, "feature:access");
|
||||
|
||||
AuthzClient authzClient = getAuthzClient(AUTHZ_CLIENT_CONFIG);
|
||||
|
||||
AuthorizationResponse response = authzClient.authorization().authorize(request);
|
||||
AccessToken token = toAccessToken(response.getToken());
|
||||
Authorization result = token.getAuthorization();
|
||||
|
||||
assertEquals(2, result.getPermissions().size());
|
||||
assertTrue(result.getPermissions().stream().anyMatch(p ->
|
||||
p.getResourceId() == null && p.getScopes().contains(featureAccessScope.getName())));
|
||||
String resourceId = resource.getId();
|
||||
assertTrue(result.getPermissions().stream().anyMatch(p ->
|
||||
p.getResourceId() != null && p.getResourceId().equals(resourceId) && p
|
||||
.getScopes().contains("entity:read")));
|
||||
|
||||
request = new AuthorizationRequest();
|
||||
|
||||
request.addPermission(null, "feature:access");
|
||||
request.addPermission(null, "entity:read");
|
||||
|
||||
response = authzClient.authorization().authorize(request);
|
||||
token = toAccessToken(response.getToken());
|
||||
result = token.getAuthorization();
|
||||
|
||||
assertEquals(2, result.getPermissions().size());
|
||||
assertTrue(result.getPermissions().stream().anyMatch(p ->
|
||||
p.getResourceId() == null && p.getScopes().contains(featureAccessScope.getName())));
|
||||
assertTrue(result.getPermissions().stream().anyMatch(p ->
|
||||
p.getResourceId() != null && p.getResourceId().equals(resourceId) && p
|
||||
.getScopes().contains("entity:read")));
|
||||
}
|
||||
|
||||
private void testRptRequestWithResourceName(String configFile) {
|
||||
Metadata metadata = new Metadata();
|
||||
|
||||
|
|
Loading…
Reference in a new issue