[KEYCLOAK-14646] - Improving permission resolution and evaluation
This commit is contained in:
parent
9204402514
commit
7501e42969
31 changed files with 542 additions and 318 deletions
|
@ -40,7 +40,7 @@ public abstract class AbstractPermissionProvider implements PolicyProvider {
|
|||
Policy policy = evaluation.getPolicy();
|
||||
ResourcePermission permission = evaluation.getPermission();
|
||||
|
||||
policy.getAssociatedPolicies().forEach(associatedPolicy -> {
|
||||
for (Policy associatedPolicy : policy.getAssociatedPolicies()) {
|
||||
Map<Object, Decision.Effect> decisions = decisionCache.computeIfAbsent(associatedPolicy, p -> new HashMap<>());
|
||||
Decision.Effect effect = decisions.get(permission);
|
||||
|
||||
|
@ -59,7 +59,7 @@ public abstract class AbstractPermissionProvider implements PolicyProvider {
|
|||
} else {
|
||||
defaultEvaluation.setEffect(effect);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -133,8 +133,9 @@ public class ResourceAdapter implements Resource, CachedModel<Resource> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourceServer getResourceServer() {
|
||||
return cacheSession.getResourceServerStore().findById(cached.getResourceServerId());
|
||||
public String getResourceServer() {
|
||||
if (isUpdated()) return updated.getResourceServer();
|
||||
return cached.getResourceServerId();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -203,7 +204,7 @@ public class ResourceAdapter implements Resource, CachedModel<Resource> {
|
|||
for (Scope scope : updated.getScopes()) {
|
||||
if (!scopes.contains(scope)) {
|
||||
PermissionTicketStore permissionStore = cacheSession.getPermissionTicketStore();
|
||||
List<PermissionTicket> permissions = permissionStore.findByScope(scope.getId(), getResourceServer().getId());
|
||||
List<PermissionTicket> permissions = permissionStore.findByScope(scope.getId(), getResourceServer());
|
||||
|
||||
for (PermissionTicket permission : permissions) {
|
||||
permissionStore.delete(permission.getId());
|
||||
|
@ -215,7 +216,7 @@ public class ResourceAdapter implements Resource, CachedModel<Resource> {
|
|||
|
||||
for (Scope scope : updated.getScopes()) {
|
||||
if (!scopes.contains(scope)) {
|
||||
policyStore.findByResource(getId(), getResourceServer().getId(), policy -> policy.removeScope(scope));
|
||||
policyStore.findByResource(getId(), getResourceServer(), policy -> policy.removeScope(scope));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -601,8 +601,8 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
if (resource == null) return;
|
||||
|
||||
cache.invalidateObject(id);
|
||||
invalidationEvents.add(ResourceRemovedEvent.create(id, resource.getName(), resource.getType(), resource.getUris(), resource.getOwner(), resource.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toSet()), resource.getResourceServer().getId()));
|
||||
cache.resourceRemoval(id, resource.getName(), resource.getType(), resource.getUris(), resource.getOwner(), resource.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toSet()), resource.getResourceServer().getId(), invalidations);
|
||||
invalidationEvents.add(ResourceRemovedEvent.create(id, resource.getName(), resource.getType(), resource.getUris(), resource.getOwner(), resource.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toSet()), resource.getResourceServer()));
|
||||
cache.resourceRemoval(id, resource.getName(), resource.getType(), resource.getUris(), resource.getOwner(), resource.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toSet()), resource.getResourceServer(), invalidations);
|
||||
getResourceStoreDelegate().delete(id);
|
||||
|
||||
}
|
||||
|
@ -672,7 +672,17 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
@Override
|
||||
public void findByOwner(String ownerId, String resourceServerId, Consumer<Resource> consumer) {
|
||||
String cacheKey = getResourceByOwnerCacheKey(ownerId, resourceServerId);
|
||||
cacheQuery(cacheKey, ResourceListQuery.class, () -> getResourceStoreDelegate().findByOwner(ownerId, resourceServerId),
|
||||
cacheQuery(cacheKey, ResourceListQuery.class, () -> {
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
getResourceStoreDelegate().findByOwner(ownerId, resourceServerId, new Consumer<Resource>() {
|
||||
@Override
|
||||
public void accept(Resource resource) {
|
||||
resources.add(resource);
|
||||
consumer.accept(resource);
|
||||
}
|
||||
});
|
||||
return resources;
|
||||
},
|
||||
(revision, resources) -> new ResourceListQuery(revision, cacheKey, resources.stream().map(resource -> resource.getId()).collect(Collectors.toSet()), resourceServerId), resourceServerId, consumer);
|
||||
}
|
||||
|
||||
|
@ -718,7 +728,17 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
|
||||
for (String id : ids) {
|
||||
String cacheKey = getResourceByScopeCacheKey(id, resourceServerId);
|
||||
cacheQuery(cacheKey, ResourceScopeListQuery.class, () -> getResourceStoreDelegate().findByScope(Arrays.asList(id), resourceServerId), (revision, resources) -> new ResourceScopeListQuery(revision, cacheKey, id, resources.stream().map(resource -> resource.getId()).collect(Collectors.toSet()), resourceServerId), resourceServerId, consumer);
|
||||
cacheQuery(cacheKey, ResourceScopeListQuery.class, () -> {
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
getResourceStoreDelegate().findByScope(Arrays.asList(id), resourceServerId, new Consumer<Resource>() {
|
||||
@Override
|
||||
public void accept(Resource resource) {
|
||||
resources.add(resource);
|
||||
consumer.accept(resource);
|
||||
}
|
||||
});
|
||||
return resources;
|
||||
}, (revision, resources) -> new ResourceScopeListQuery(revision, cacheKey, id, resources.stream().map(resource -> resource.getId()).collect(Collectors.toSet()), resourceServerId), resourceServerId, consumer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -734,7 +754,17 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
public void findByType(String type, String resourceServerId, Consumer<Resource> consumer) {
|
||||
if (type == null) return;
|
||||
String cacheKey = getResourceByTypeCacheKey(type, resourceServerId);
|
||||
cacheQuery(cacheKey, ResourceListQuery.class, () -> getResourceStoreDelegate().findByType(type, resourceServerId),
|
||||
cacheQuery(cacheKey, ResourceListQuery.class, () -> {
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
getResourceStoreDelegate().findByType(type, resourceServerId, new Consumer<Resource>() {
|
||||
@Override
|
||||
public void accept(Resource resource) {
|
||||
resources.add(resource);
|
||||
consumer.accept(resource);
|
||||
}
|
||||
});
|
||||
return resources;
|
||||
},
|
||||
(revision, resources) -> new ResourceListQuery(revision, cacheKey, resources.stream().map(resource -> resource.getId()).collect(Collectors.toSet()), resourceServerId), resourceServerId, consumer);
|
||||
}
|
||||
|
||||
|
@ -754,7 +784,17 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
public void findByType(String type, String owner, String resourceServerId, Consumer<Resource> consumer) {
|
||||
if (type == null) return;
|
||||
String cacheKey = getResourceByTypeCacheKey(type, owner, resourceServerId);
|
||||
cacheQuery(cacheKey, ResourceListQuery.class, () -> getResourceStoreDelegate().findByType(type, owner, resourceServerId),
|
||||
cacheQuery(cacheKey, ResourceListQuery.class, () -> {
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
getResourceStoreDelegate().findByType(type, owner, resourceServerId, new Consumer<Resource>() {
|
||||
@Override
|
||||
public void accept(Resource resource) {
|
||||
resources.add(resource);
|
||||
consumer.accept(resource);
|
||||
}
|
||||
});
|
||||
return resources;
|
||||
},
|
||||
(revision, resources) -> new ResourceListQuery(revision, cacheKey, resources.stream().map(resource -> resource.getId()).collect(Collectors.toSet()), resourceServerId), resourceServerId, consumer);
|
||||
}
|
||||
|
||||
|
@ -770,7 +810,17 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
public void findByTypeInstance(String type, String resourceServerId, Consumer<Resource> consumer) {
|
||||
if (type == null) return;
|
||||
String cacheKey = getResourceByTypeInstanceCacheKey(type, resourceServerId);
|
||||
cacheQuery(cacheKey, ResourceListQuery.class, () -> getResourceStoreDelegate().findByTypeInstance(type, resourceServerId),
|
||||
cacheQuery(cacheKey, ResourceListQuery.class, () -> {
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
getResourceStoreDelegate().findByTypeInstance(type, resourceServerId, new Consumer<Resource>() {
|
||||
@Override
|
||||
public void accept(Resource resource) {
|
||||
resources.add(resource);
|
||||
consumer.accept(resource);
|
||||
}
|
||||
});
|
||||
return resources;
|
||||
},
|
||||
(revision, resources) -> new ResourceListQuery(revision, cacheKey, resources.stream().map(resource -> resource.getId()).collect(Collectors.toSet()), resourceServerId), resourceServerId, consumer);
|
||||
}
|
||||
|
||||
|
@ -788,20 +838,10 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
List<R> model = resultSupplier.get();
|
||||
if (model == null) return null;
|
||||
if (invalidations.contains(cacheKey)) {
|
||||
if (consumer != null) {
|
||||
for (R policy: model) {
|
||||
consumer.accept(policy);
|
||||
}
|
||||
}
|
||||
return model;
|
||||
};
|
||||
query = querySupplier.apply(loaded, model);
|
||||
cache.addRevisioned(query, startupRevision);
|
||||
if (consumer != null) {
|
||||
for (R resource : model) {
|
||||
consumer.andThen(r -> cacheResource(resource)).accept(resource);
|
||||
}
|
||||
}
|
||||
return model;
|
||||
} else if (query.isInvalid(invalidations)) {
|
||||
List<R> result = resultSupplier.get();
|
||||
|
@ -929,7 +969,17 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
@Override
|
||||
public void findByResource(String resourceId, String resourceServerId, Consumer<Policy> consumer) {
|
||||
String cacheKey = getPolicyByResource(resourceId, resourceServerId);
|
||||
cacheQuery(cacheKey, PolicyResourceListQuery.class, () -> getPolicyStoreDelegate().findByResource(resourceId, resourceServerId),
|
||||
cacheQuery(cacheKey, PolicyResourceListQuery.class, () -> {
|
||||
List<Policy> policies = new ArrayList<>();
|
||||
getPolicyStoreDelegate().findByResource(resourceId, resourceServerId, new Consumer<Policy>() {
|
||||
@Override
|
||||
public void accept(Policy policy) {
|
||||
policies.add(policy);
|
||||
consumer.accept(policy);
|
||||
}
|
||||
});
|
||||
return policies;
|
||||
},
|
||||
(revision, policies) -> new PolicyResourceListQuery(revision, cacheKey, resourceId, policies.stream().map(policy -> policy.getId()).collect(Collectors.toSet()), resourceServerId), resourceServerId, consumer);
|
||||
}
|
||||
|
||||
|
@ -943,7 +993,17 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
@Override
|
||||
public void findByResourceType(String resourceType, String resourceServerId, Consumer<Policy> consumer) {
|
||||
String cacheKey = getPolicyByResourceType(resourceType, resourceServerId);
|
||||
cacheQuery(cacheKey, PolicyResourceListQuery.class, () -> getPolicyStoreDelegate().findByResourceType(resourceType, resourceServerId),
|
||||
cacheQuery(cacheKey, PolicyResourceListQuery.class, () -> {
|
||||
List<Policy> policies = new ArrayList<>();
|
||||
getPolicyStoreDelegate().findByResourceType(resourceType, resourceServerId, new Consumer<Policy>() {
|
||||
@Override
|
||||
public void accept(Policy policy) {
|
||||
policies.add(policy);
|
||||
consumer.accept(policy);
|
||||
}
|
||||
});
|
||||
return policies;
|
||||
},
|
||||
(revision, policies) -> new PolicyResourceListQuery(revision, cacheKey, resourceType, policies.stream().map(policy -> policy.getId()).collect(Collectors.toSet()), resourceServerId), resourceServerId, consumer);
|
||||
}
|
||||
|
||||
|
@ -977,7 +1037,15 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
public void findByScopeIds(List<String> scopeIds, String resourceId, String resourceServerId, Consumer<Policy> consumer) {
|
||||
for (String id : scopeIds) {
|
||||
String cacheKey = getPolicyByResourceScope(id, resourceId, resourceServerId);
|
||||
cacheQuery(cacheKey, PolicyScopeListQuery.class, () -> getPolicyStoreDelegate().findByScopeIds(Arrays.asList(id), resourceId, resourceServerId), (revision, resources) -> new PolicyScopeListQuery(revision, cacheKey, id, resources.stream().map(resource -> resource.getId()).collect(Collectors.toSet()), resourceServerId), resourceServerId, consumer);
|
||||
cacheQuery(cacheKey, PolicyScopeListQuery.class, () -> {
|
||||
List<Policy> policies = new ArrayList<>();
|
||||
getPolicyStoreDelegate().findByScopeIds(Arrays.asList(id), resourceId, resourceServerId,
|
||||
policy -> {
|
||||
policies.add(policy);
|
||||
consumer.accept(policy);
|
||||
});
|
||||
return policies;
|
||||
}, (revision, resources) -> new PolicyScopeListQuery(revision, cacheKey, id, resources.stream().map(resource -> resource.getId()).collect(Collectors.toSet()), resourceServerId), resourceServerId, consumer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1010,11 +1078,6 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
|||
};
|
||||
query = querySupplier.apply(loaded, model);
|
||||
cache.addRevisioned(query, startupRevision);
|
||||
if (consumer != null) {
|
||||
for (R policy: model) {
|
||||
consumer.andThen(r -> cachePolicy(policy)).accept(policy);
|
||||
}
|
||||
}
|
||||
return model;
|
||||
} else if (query.isInvalid(invalidations)) {
|
||||
List<R> policies = resultSupplier.get();
|
||||
|
|
|
@ -56,7 +56,7 @@ public class CachedResource extends AbstractRevisioned implements InResourceServ
|
|||
this.type = resource.getType();
|
||||
this.owner = resource.getOwner();
|
||||
this.iconUri = resource.getIconUri();
|
||||
this.resourceServerId = resource.getResourceServer().getId();
|
||||
this.resourceServerId = resource.getResourceServer();
|
||||
ownerManagedAccess = resource.isOwnerManagedAccess();
|
||||
|
||||
if (resource.isFetched("uris")) {
|
||||
|
|
|
@ -39,7 +39,7 @@ import javax.persistence.UniqueConstraint;
|
|||
})
|
||||
@NamedQueries(
|
||||
{
|
||||
@NamedQuery(name="findPermissionIdByResource", query="select p.id from PermissionTicketEntity p inner join p.resource r where p.resourceServer.id = :serverId and (r.resourceServer.id = :serverId and r.id = :resourceId)"),
|
||||
@NamedQuery(name="findPermissionIdByResource", query="select p.id from PermissionTicketEntity p inner join p.resource r where p.resourceServer.id = :serverId and (r.resourceServer = :serverId and r.id = :resourceId)"),
|
||||
@NamedQuery(name="findPermissionIdByScope", query="select p.id from PermissionTicketEntity p inner join p.scope s where p.resourceServer.id = :serverId and (s.resourceServer.id = :serverId and s.id = :scopeId)"),
|
||||
@NamedQuery(name="findPermissionTicketIdByServerId", query="select p.id from PermissionTicketEntity p where p.resourceServer.id = :serverId "),
|
||||
@NamedQuery(name="findGrantedResources", query="select distinct(r.id) from ResourceEntity r inner join PermissionTicketEntity p on r.id = p.resource.id where p.grantedTimestamp is not null and p.requester = :requester order by r.id"),
|
||||
|
|
|
@ -38,6 +38,9 @@ import javax.persistence.OneToMany;
|
|||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.hibernate.annotations.BatchSize;
|
||||
import org.hibernate.annotations.Fetch;
|
||||
import org.hibernate.annotations.FetchMode;
|
||||
import org.hibernate.annotations.Nationalized;
|
||||
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
||||
import org.keycloak.representations.idm.authorization.Logic;
|
||||
|
@ -53,10 +56,10 @@ import org.keycloak.representations.idm.authorization.Logic;
|
|||
{
|
||||
@NamedQuery(name="findPolicyIdByServerId", query="select p.id from PolicyEntity p where p.resourceServer.id = :serverId "),
|
||||
@NamedQuery(name="findPolicyIdByName", query="select p from PolicyEntity p left join fetch p.associatedPolicies a where p.resourceServer.id = :serverId and p.name = :name"),
|
||||
@NamedQuery(name="findPolicyIdByResource", query="select p from PolicyEntity p inner join p.resources r inner join fetch p.associatedPolicies a where p.resourceServer.id = :serverId and (r.resourceServer.id = :serverId and r.id = :resourceId)"),
|
||||
@NamedQuery(name="findPolicyIdByResource", query="select p from PolicyEntity p inner join p.resources r where p.resourceServer.id = :serverId and (r.resourceServer = :serverId and r.id = :resourceId)"),
|
||||
@NamedQuery(name="findPolicyIdByScope", query="select pe from PolicyEntity pe inner join pe.scopes s inner join fetch pe.associatedPolicies a where pe.resourceServer.id = :serverId and exists (select p.id from ScopeEntity s inner join s.policies p where s.resourceServer.id = :serverId and (p.resourceServer.id = :serverId and p.type = 'scope' and s.id in (:scopeIds) and p.id = pe.id))"),
|
||||
@NamedQuery(name="findPolicyIdByResourceScope", query="select pe from PolicyEntity pe inner join pe.resources r inner join pe.scopes s inner join fetch pe.associatedPolicies a where pe.resourceServer.id = :serverId and exists (select p.id from ScopeEntity s inner join s.policies p where s.resourceServer.id = :serverId and (p.resourceServer.id = :serverId and p.type = 'scope' and s.id in (:scopeIds) and p.id = pe.id)) and exists (select p.id from ResourceEntity r inner join r.policies p where r.resourceServer.id = :serverId and (p.resourceServer.id = :serverId and p.id = pe.id and p.type = 'scope' and r.id in (:resourceId)))"),
|
||||
@NamedQuery(name="findPolicyIdByNullResourceScope", query="select pe from PolicyEntity pe left join fetch pe.config c inner join pe.scopes s inner join fetch pe.associatedPolicies a where pe.resourceServer.id = :serverId and exists (select p.id from ScopeEntity s inner join s.policies p where s.resourceServer.id = :serverId and (p.resourceServer.id = :serverId and p.id = pe.id and p.type = 'scope' and s.id in (:scopeIds))) and pe.resources is empty and not exists (select pec from pe.config pec where KEY(pec) = 'defaultResourceType')"),
|
||||
@NamedQuery(name="findPolicyIdByResourceScope", query="select pe from PolicyEntity pe inner join pe.resources r inner join pe.scopes s inner join fetch pe.associatedPolicies a where pe.resourceServer.id = :serverId and exists (select p.id from ScopeEntity s inner join s.policies p where s.resourceServer.id = :serverId and (p.resourceServer.id = :serverId and p.type = 'scope' and s.id in (:scopeIds) and p.id = pe.id)) and exists (select p.id from ResourceEntity r inner join r.policies p where r.resourceServer = :serverId and (p.resourceServer.id = :serverId and p.id = pe.id and p.type = 'scope' and r.id in (:resourceId)))"),
|
||||
@NamedQuery(name="findPolicyIdByNullResourceScope", query="select pe from PolicyEntity pe left join fetch pe.config c inner join pe.scopes s inner join pe.associatedPolicies a where pe.resourceServer.id = :serverId and pe.type = 'scope' and pe.resources is empty and exists (select p.id from ScopeEntity s inner join s.policies p where s.resourceServer.id = :serverId and (p.resourceServer.id = :serverId and p.id = pe.id and s.id in (:scopeIds))) and not exists (select pec from pe.config pec where KEY(pec) = 'defaultResourceType')"),
|
||||
@NamedQuery(name="findPolicyIdByType", query="select p.id from PolicyEntity p where p.resourceServer.id = :serverId and p.type = :type"),
|
||||
@NamedQuery(name="findPolicyIdByResourceType", query="select p from PolicyEntity p inner join p.config c inner join fetch p.associatedPolicies a where p.resourceServer.id = :serverId and KEY(c) = 'defaultResourceType' and c like :type"),
|
||||
@NamedQuery(name="findPolicyIdByDependentPolices", query="select p.id from PolicyEntity p inner join p.associatedPolicies ap where p.resourceServer.id = :serverId and (ap.resourceServer.id = :serverId and ap.id = :policyId)"),
|
||||
|
@ -98,8 +101,10 @@ public class PolicyEntity {
|
|||
@JoinColumn(name = "RESOURCE_SERVER_ID")
|
||||
private ResourceServerEntity resourceServer;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, cascade = {})
|
||||
@OneToMany(fetch = FetchType.EAGER, cascade = {})
|
||||
@JoinTable(name = "ASSOCIATED_POLICY", joinColumns = @JoinColumn(name = "POLICY_ID"), inverseJoinColumns = @JoinColumn(name = "ASSOCIATED_POLICY_ID"))
|
||||
@Fetch(FetchMode.SELECT)
|
||||
@BatchSize(size = 20)
|
||||
private Set<PolicyEntity> associatedPolicies;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, cascade = {})
|
||||
|
|
|
@ -57,18 +57,18 @@ import org.hibernate.annotations.FetchMode;
|
|||
})
|
||||
@NamedQueries(
|
||||
{
|
||||
@NamedQuery(name="findResourceIdByOwner", query="select distinct(r.id) from ResourceEntity r left join r.scopes s where r.resourceServer.id = :serverId and r.owner = :owner"),
|
||||
@NamedQuery(name="findResourceIdByOwnerOrdered", query="select distinct(r.id) from ResourceEntity r where r.resourceServer.id = :serverId and r.owner = :owner order by r.id"),
|
||||
@NamedQuery(name="findAnyResourceIdByOwner", query="select distinct(r.id) from ResourceEntity r where r.owner = :owner"),
|
||||
@NamedQuery(name="findAnyResourceIdByOwnerOrdered", query="select distinct(r.id) from ResourceEntity r where r.owner = :owner order by r.id"),
|
||||
@NamedQuery(name="findResourceIdByUri", query="select r.id from ResourceEntity r where r.resourceServer.id = :serverId and :uri in elements(r.uris)"),
|
||||
@NamedQuery(name="findResourceIdByName", query="select distinct(r) from ResourceEntity r left join fetch r.scopes s where r.resourceServer.id = :serverId and r.owner = :ownerId and r.name = :name"),
|
||||
@NamedQuery(name="findResourceIdByType", query="select distinct(r) from ResourceEntity r left join fetch r.scopes s where r.resourceServer.id = :serverId and r.owner = :ownerId and r.type = :type"),
|
||||
@NamedQuery(name="findResourceIdByTypeNoOwner", query="select distinct(r) from ResourceEntity r left join fetch r.scopes s where r.resourceServer.id = :serverId and r.type = :type"),
|
||||
@NamedQuery(name="findResourceIdByTypeInstance", query="select distinct(r) from ResourceEntity r left join fetch r.scopes s where r.resourceServer.id = :serverId and r.type = :type and r.owner <> :serverId"),
|
||||
@NamedQuery(name="findResourceIdByServerId", query="select r.id from ResourceEntity r where r.resourceServer.id = :serverId "),
|
||||
@NamedQuery(name="findResourceIdByScope", query="select r from ResourceEntity r inner join r.scopes s where r.resourceServer.id = :serverId and (s.resourceServer.id = :serverId and s.id in (:scopeIds))"),
|
||||
@NamedQuery(name="deleteResourceByResourceServer", query="delete from ResourceEntity r where r.resourceServer.id = :serverId")
|
||||
@NamedQuery(name="findResourceIdByOwner", query="select r from ResourceEntity r where r.resourceServer = :serverId and r.owner = :owner"),
|
||||
@NamedQuery(name="findResourceIdByOwnerOrdered", query="select r from ResourceEntity r where r.resourceServer = :serverId and r.owner = :owner order by r.id"),
|
||||
@NamedQuery(name="findAnyResourceIdByOwner", query="select r from ResourceEntity r where r.owner = :owner"),
|
||||
@NamedQuery(name="findAnyResourceIdByOwnerOrdered", query="select r.id from ResourceEntity r where r.owner = :owner order by r.id"),
|
||||
@NamedQuery(name="findResourceIdByUri", query="select r.id from ResourceEntity r where r.resourceServer = :serverId and :uri in elements(r.uris)"),
|
||||
@NamedQuery(name="findResourceIdByName", query="select r from ResourceEntity r left join fetch r.scopes s where r.resourceServer = :serverId and r.owner = :ownerId and r.name = :name"),
|
||||
@NamedQuery(name="findResourceIdByType", query="select r from ResourceEntity r left join fetch r.scopes s where r.resourceServer = :serverId and r.owner = :ownerId and r.type = :type"),
|
||||
@NamedQuery(name="findResourceIdByTypeNoOwner", query="select r from ResourceEntity r left join fetch r.scopes s where r.resourceServer = :serverId and r.type = :type"),
|
||||
@NamedQuery(name="findResourceIdByTypeInstance", query="select r from ResourceEntity r left join fetch r.scopes s where r.resourceServer = :serverId and r.type = :type and r.owner <> :serverId"),
|
||||
@NamedQuery(name="findResourceIdByServerId", query="select r.id from ResourceEntity r where r.resourceServer = :serverId "),
|
||||
@NamedQuery(name="findResourceIdByScope", query="select r from ResourceEntity r inner join r.scopes s where r.resourceServer = :serverId and (s.resourceServer = :serverId and s.id in (:scopeIds))"),
|
||||
@NamedQuery(name="deleteResourceByResourceServer", query="delete from ResourceEntity r where r.resourceServer = :serverId")
|
||||
}
|
||||
)
|
||||
public class ResourceEntity {
|
||||
|
@ -101,12 +101,13 @@ public class ResourceEntity {
|
|||
@Column(name = "OWNER_MANAGED_ACCESS")
|
||||
private boolean ownerManagedAccess;
|
||||
|
||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "RESOURCE_SERVER_ID")
|
||||
private ResourceServerEntity resourceServer;
|
||||
@Column(name = "RESOURCE_SERVER_ID")
|
||||
private String resourceServer;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, cascade = {})
|
||||
@JoinTable(name = "RESOURCE_SCOPE", joinColumns = @JoinColumn(name = "RESOURCE_ID"), inverseJoinColumns = @JoinColumn(name = "SCOPE_ID"))
|
||||
@Fetch(FetchMode.SELECT)
|
||||
@BatchSize(size = 20)
|
||||
private List<ScopeEntity> scopes;
|
||||
|
||||
@ManyToMany(fetch = FetchType.LAZY, cascade = {})
|
||||
|
@ -176,11 +177,11 @@ public class ResourceEntity {
|
|||
this.iconUri = iconUri;
|
||||
}
|
||||
|
||||
public ResourceServerEntity getResourceServer() {
|
||||
public String getResourceServer() {
|
||||
return resourceServer;
|
||||
}
|
||||
|
||||
public void setResourceServer(ResourceServerEntity resourceServer) {
|
||||
public void setResourceServer(String resourceServer) {
|
||||
this.resourceServer = resourceServer;
|
||||
}
|
||||
|
||||
|
|
|
@ -213,10 +213,11 @@ public class JPAPolicyStore implements PolicyStore {
|
|||
query.setParameter("resourceId", resourceId);
|
||||
query.setParameter("serverId", resourceServerId);
|
||||
|
||||
StoreFactory storeFactory = provider.getStoreFactory();
|
||||
PolicyStore storeFactory = provider.getStoreFactory().getPolicyStore();
|
||||
|
||||
query.getResultList().stream()
|
||||
.map(entity -> new PolicyAdapter(entity, entityManager, storeFactory))
|
||||
query.getResultStream()
|
||||
.map(entity -> storeFactory.findById(entity.getId(), resourceServerId))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(consumer::accept);
|
||||
}
|
||||
|
||||
|
@ -237,8 +238,9 @@ public class JPAPolicyStore implements PolicyStore {
|
|||
query.setParameter("type", resourceType);
|
||||
query.setParameter("serverId", resourceServerId);
|
||||
|
||||
query.getResultList().stream()
|
||||
query.getResultStream()
|
||||
.map(id -> new PolicyAdapter(id, entityManager, provider.getStoreFactory()))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(consumer::accept);
|
||||
}
|
||||
|
||||
|
@ -256,10 +258,10 @@ public class JPAPolicyStore implements PolicyStore {
|
|||
query.setParameter("serverId", resourceServerId);
|
||||
|
||||
List<Policy> list = new LinkedList<>();
|
||||
StoreFactory storeFactory = provider.getStoreFactory();
|
||||
PolicyStore storeFactory = provider.getStoreFactory().getPolicyStore();
|
||||
|
||||
for (PolicyEntity entity : query.getResultList()) {
|
||||
list.add(new PolicyAdapter(entity, entityManager, storeFactory));
|
||||
list.add(storeFactory.findById(entity.getId(), resourceServerId));
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -292,8 +294,9 @@ public class JPAPolicyStore implements PolicyStore {
|
|||
|
||||
StoreFactory storeFactory = provider.getStoreFactory();
|
||||
|
||||
query.getResultList().stream()
|
||||
query.getResultStream()
|
||||
.map(id -> new PolicyAdapter(id, entityManager, storeFactory))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(consumer::accept);
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ public class JPAResourceStore implements ResourceStore {
|
|||
}
|
||||
|
||||
entity.setName(name);
|
||||
entity.setResourceServer(ResourceServerAdapter.toEntity(entityManager, resourceServer));
|
||||
entity.setResourceServer(ResourceServerAdapter.toEntity(entityManager, resourceServer).getId());
|
||||
entity.setOwner(owner);
|
||||
|
||||
this.entityManager.persist(entity);
|
||||
|
@ -130,7 +130,7 @@ public class JPAResourceStore implements ResourceStore {
|
|||
queryName = pagination ? "findAnyResourceIdByOwnerOrdered" : "findAnyResourceIdByOwner";
|
||||
}
|
||||
|
||||
TypedQuery<String> query = entityManager.createNamedQuery(queryName, String.class);
|
||||
TypedQuery<ResourceEntity> query = entityManager.createNamedQuery(queryName, ResourceEntity.class);
|
||||
|
||||
query.setFlushMode(FlushModeType.COMMIT);
|
||||
query.setParameter("owner", ownerId);
|
||||
|
@ -145,15 +145,7 @@ public class JPAResourceStore implements ResourceStore {
|
|||
}
|
||||
|
||||
ResourceStore resourceStore = provider.getStoreFactory().getResourceStore();
|
||||
List<String> result = query.getResultList();
|
||||
|
||||
for (String entity : result) {
|
||||
Resource cached = resourceStore.findById(entity, resourceServerId);
|
||||
|
||||
if (cached != null) {
|
||||
consumer.accept(cached);
|
||||
}
|
||||
}
|
||||
query.getResultStream().map(id -> resourceStore.findById(id.getId(), resourceServerId)).forEach(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -209,7 +201,7 @@ public class JPAResourceStore implements ResourceStore {
|
|||
List<Predicate> predicates = new ArrayList();
|
||||
|
||||
if (resourceServerId != null) {
|
||||
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
||||
predicates.add(builder.equal(root.get("resourceServer"), resourceServerId));
|
||||
}
|
||||
|
||||
attributes.forEach((name, value) -> {
|
||||
|
|
|
@ -117,7 +117,7 @@ public class ResourceAdapter extends AbstractAuthorizationModel implements Resou
|
|||
public List<Scope> getScopes() {
|
||||
List<Scope> scopes = new LinkedList<>();
|
||||
for (ScopeEntity scope : entity.getScopes()) {
|
||||
scopes.add(storeFactory.getScopeStore().findById(scope.getId(), entity.getResourceServer().getId()));
|
||||
scopes.add(storeFactory.getScopeStore().findById(scope.getId(), entity.getResourceServer()));
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(scopes);
|
||||
|
@ -136,9 +136,8 @@ public class ResourceAdapter extends AbstractAuthorizationModel implements Resou
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourceServer getResourceServer() {
|
||||
ResourceServer temp = storeFactory.getResourceServerStore().findById(entity.getResourceServer().getId());
|
||||
return temp;
|
||||
public String getResourceServer() {
|
||||
return entity.getResourceServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -455,14 +455,14 @@ public final class AuthorizationProvider implements Provider {
|
|||
Resource resource = findById(id, null);
|
||||
StoreFactory storeFactory = AuthorizationProvider.this.getStoreFactory();
|
||||
PermissionTicketStore ticketStore = storeFactory.getPermissionTicketStore();
|
||||
List<PermissionTicket> permissions = ticketStore.findByResource(id, resource.getResourceServer().getId());
|
||||
List<PermissionTicket> permissions = ticketStore.findByResource(id, resource.getResourceServer());
|
||||
|
||||
for (PermissionTicket permission : permissions) {
|
||||
ticketStore.delete(permission.getId());
|
||||
}
|
||||
|
||||
PolicyStore policyStore = storeFactory.getPolicyStore();
|
||||
List<Policy> policies = policyStore.findByResource(id, resource.getResourceServer().getId());
|
||||
List<Policy> policies = policyStore.findByResource(id, resource.getResourceServer());
|
||||
|
||||
for (Policy policyModel : policies) {
|
||||
if (policyModel.getResources().size() == 1) {
|
||||
|
|
|
@ -121,7 +121,7 @@ public interface Resource {
|
|||
*
|
||||
* @return the resource server associated with this resource
|
||||
*/
|
||||
ResourceServer getResourceServer();
|
||||
String getResourceServer();
|
||||
|
||||
/**
|
||||
* Returns the resource's owner, which is usually an identifier that uniquely identifies the resource's owner.
|
||||
|
|
|
@ -16,15 +16,18 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.authorization.util;
|
||||
package org.keycloak.authorization.permission;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
|
@ -33,7 +36,6 @@ import org.keycloak.authorization.model.PermissionTicket;
|
|||
import org.keycloak.authorization.model.Resource;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.model.Scope;
|
||||
import org.keycloak.authorization.permission.ResourcePermission;
|
||||
import org.keycloak.authorization.store.ResourceStore;
|
||||
import org.keycloak.authorization.store.StoreFactory;
|
||||
import org.keycloak.representations.idm.authorization.AuthorizationRequest;
|
||||
|
@ -58,8 +60,7 @@ public final class Permissions {
|
|||
* @param authorization
|
||||
* @return
|
||||
*/
|
||||
public static List<ResourcePermission> all(ResourceServer resourceServer, Identity identity, AuthorizationProvider authorization, AuthorizationRequest request) {
|
||||
List<ResourcePermission> permissions = new ArrayList<>();
|
||||
public static void all(ResourceServer resourceServer, Identity identity, AuthorizationProvider authorization, AuthorizationRequest request, Consumer<ResourcePermission> evaluator) {
|
||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||
ResourceStore resourceStore = storeFactory.getResourceStore();
|
||||
Metadata metadata = request.getMetadata();
|
||||
|
@ -74,7 +75,7 @@ public final class Permissions {
|
|||
// obtain all resources where owner is the resource server
|
||||
resourceStore.findByOwner(resourceServer.getId(), resourceServer.getId(), resource -> {
|
||||
if (limit.decrementAndGet() >= 0) {
|
||||
permissions.add(createResourcePermissions(resource, authorization, request));
|
||||
evaluator.accept(createResourcePermissions(resource, resourceServer, resource.getScopes(), authorization, request));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -83,7 +84,7 @@ public final class Permissions {
|
|||
// obtain all resources where owner is the current user
|
||||
resourceStore.findByOwner(identity.getId(), resourceServer.getId(), resource -> {
|
||||
if (limit.decrementAndGet() >= 0) {
|
||||
permissions.add(createResourcePermissions(resource, authorization, request));
|
||||
evaluator.accept(createResourcePermissions(resource, resourceServer, resource.getScopes(), authorization, request));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -95,59 +96,56 @@ public final class Permissions {
|
|||
Map<String, ResourcePermission> userManagedPermissions = new HashMap<>();
|
||||
|
||||
for (PermissionTicket ticket : tickets) {
|
||||
ResourcePermission permission = userManagedPermissions.get(ticket.getResource().getId());
|
||||
|
||||
if (permission == null) {
|
||||
userManagedPermissions.put(ticket.getResource().getId(), new ResourcePermission(ticket.getResource(), new ArrayList<>(), resourceServer, request.getClaims()));
|
||||
limit.decrementAndGet();
|
||||
}
|
||||
|
||||
if (limit.decrementAndGet() <= 0) {
|
||||
if (limit.get() < 0) {
|
||||
break;
|
||||
}
|
||||
ResourcePermission permission = userManagedPermissions.computeIfAbsent(ticket.getResource().getId(),
|
||||
s -> {
|
||||
limit.decrementAndGet();
|
||||
ResourcePermission resourcePermission = new ResourcePermission(ticket.getResource(),
|
||||
new ArrayList<>(), resourceServer,
|
||||
request.getClaims());
|
||||
resourcePermission.setGranted(true);
|
||||
return resourcePermission;
|
||||
});
|
||||
|
||||
permission.addScope(ticket.getScope());
|
||||
}
|
||||
|
||||
permissions.addAll(userManagedPermissions.values());
|
||||
for (ResourcePermission permission : userManagedPermissions.values()) {
|
||||
evaluator.accept(permission);
|
||||
}
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public static ResourcePermission createResourcePermissions(Resource resource, Collection<Scope> requestedScopes, AuthorizationProvider authorization, AuthorizationRequest request) {
|
||||
List<Scope> scopes;
|
||||
|
||||
public static ResourcePermission createResourcePermissions(Resource resource,
|
||||
ResourceServer resourceServer, Collection<Scope> requestedScopes,
|
||||
AuthorizationProvider authorization, AuthorizationRequest request) {
|
||||
Set<Scope> scopes = resolveScopes(resource, resourceServer, requestedScopes, authorization);
|
||||
return new ResourcePermission(resource, scopes, resourceServer, request.getClaims());
|
||||
}
|
||||
|
||||
public static Set<Scope> resolveScopes(Resource resource, ResourceServer resourceServer,
|
||||
Collection<Scope> requestedScopes, AuthorizationProvider authorization) {
|
||||
if (requestedScopes.isEmpty()) {
|
||||
scopes = populateTypedScopes(resource, authorization);
|
||||
} else {
|
||||
scopes = populateTypedScopes(resource, requestedScopes.stream().filter(scope -> resource.getScopes().contains(scope)).collect(Collectors.toList()), authorization);
|
||||
return populateTypedScopes(resource, resourceServer, authorization);
|
||||
}
|
||||
|
||||
return new ResourcePermission(resource, scopes, resource.getResourceServer(), request.getClaims());
|
||||
return populateTypedScopes(resource, resourceServer, resource.getScopes(), authorization).stream()
|
||||
.filter(scope -> requestedScopes.contains(scope)).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public static ResourcePermission createResourcePermissions(Resource resource, AuthorizationProvider authorization, AuthorizationRequest request) {
|
||||
List<Scope> requestedScopes = resource.getScopes();
|
||||
|
||||
if (requestedScopes.isEmpty()) {
|
||||
return new ResourcePermission(resource, populateTypedScopes(resource, authorization), resource.getResourceServer(), request.getClaims());
|
||||
}
|
||||
|
||||
return new ResourcePermission(resource, resource.getResourceServer(), request.getClaims());
|
||||
private static Set<Scope> populateTypedScopes(Resource resource,
|
||||
ResourceServer resourceServer, AuthorizationProvider authorization) {
|
||||
return populateTypedScopes(resource, resourceServer, resource.getScopes(), authorization);
|
||||
}
|
||||
|
||||
private static List<Scope> populateTypedScopes(Resource resource, AuthorizationProvider authorization) {
|
||||
return populateTypedScopes(resource, resource.getScopes(), authorization);
|
||||
}
|
||||
|
||||
private static List<Scope> populateTypedScopes(Resource resource, List<Scope> defaultScopes, AuthorizationProvider authorization) {
|
||||
private static Set<Scope> populateTypedScopes(Resource resource, ResourceServer resourceServer, List<Scope> defaultScopes, AuthorizationProvider authorization) {
|
||||
String type = resource.getType();
|
||||
ResourceServer resourceServer = resource.getResourceServer();
|
||||
|
||||
if (type == null || resource.getOwner().equals(resourceServer.getId())) {
|
||||
return new ArrayList<>(defaultScopes);
|
||||
return new LinkedHashSet<>(defaultScopes);
|
||||
}
|
||||
|
||||
List<Scope> scopes = new ArrayList<>(defaultScopes);
|
||||
Set<Scope> scopes = new LinkedHashSet<>(defaultScopes);
|
||||
|
||||
// check if there is a typed resource whose scopes are inherited by the resource being requested. In this case, we assume that parent resource
|
||||
// is owned by the resource server itself
|
|
@ -28,7 +28,6 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
@ -41,19 +40,20 @@ import java.util.Set;
|
|||
public class ResourcePermission {
|
||||
|
||||
private final Resource resource;
|
||||
private final List<Scope> scopes;
|
||||
private final Collection<Scope> scopes;
|
||||
private ResourceServer resourceServer;
|
||||
private Map<String, Set<String>> claims;
|
||||
private boolean granted;
|
||||
|
||||
public ResourcePermission(Resource resource, List<Scope> scopes, ResourceServer resourceServer) {
|
||||
public ResourcePermission(Resource resource, Collection<Scope> scopes, ResourceServer resourceServer) {
|
||||
this(resource, scopes, resourceServer, null);
|
||||
}
|
||||
|
||||
public ResourcePermission(Resource resource, ResourceServer resourceServer, Map<String, ? extends Collection<String>> claims) {
|
||||
this(resource, new ArrayList<>(resource.getScopes()), resourceServer, claims);
|
||||
this(resource, new LinkedHashSet<>(), resourceServer, claims);
|
||||
}
|
||||
|
||||
public ResourcePermission(Resource resource, List<Scope> scopes, ResourceServer resourceServer, Map<String, ? extends Collection<String>> claims) {
|
||||
public ResourcePermission(Resource resource, Collection<Scope> scopes, ResourceServer resourceServer, Map<String, ? extends Collection<String>> claims) {
|
||||
this.resource = resource;
|
||||
this.scopes = scopes;
|
||||
this.resourceServer = resourceServer;
|
||||
|
@ -79,7 +79,7 @@ public class ResourcePermission {
|
|||
*
|
||||
* @return a lit of permitted scopes
|
||||
*/
|
||||
public List<Scope> getScopes() {
|
||||
public Collection<Scope> getScopes() {
|
||||
return this.scopes;
|
||||
}
|
||||
|
||||
|
@ -149,4 +149,12 @@ public class ResourcePermission {
|
|||
}
|
||||
this.claims.putAll(claims);
|
||||
}
|
||||
|
||||
public void setGranted(boolean granted) {
|
||||
this.granted = granted;
|
||||
}
|
||||
|
||||
public boolean isGranted() {
|
||||
return granted;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
package org.keycloak.authorization.permission.evaluator;
|
||||
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.permission.ResourcePermission;
|
||||
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
|
||||
import org.keycloak.representations.idm.authorization.AuthorizationRequest;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
@ -40,4 +42,8 @@ public final class Evaluators {
|
|||
public PermissionEvaluator from(Collection<ResourcePermission> permissions, EvaluationContext evaluationContext) {
|
||||
return new IterablePermissionEvaluator(permissions.iterator(), evaluationContext, authorizationProvider);
|
||||
}
|
||||
|
||||
public PermissionEvaluator from(EvaluationContext evaluationContext, ResourceServer resourceServer, AuthorizationRequest request) {
|
||||
return new UnboundedPermissionEvaluator(evaluationContext, authorizationProvider, resourceServer, request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,8 +60,10 @@ class IterablePermissionEvaluator implements PermissionEvaluator {
|
|||
|
||||
storeFactory.setReadOnly(true);
|
||||
|
||||
while (this.permissions.hasNext()) {
|
||||
this.policyEvaluator.evaluate(this.permissions.next(), authorizationProvider, executionContext, decision, decisionCache);
|
||||
Iterator<ResourcePermission> permissions = getPermissions();
|
||||
|
||||
while (permissions.hasNext()) {
|
||||
this.policyEvaluator.evaluate(permissions.next(), authorizationProvider, executionContext, decision, decisionCache);
|
||||
}
|
||||
|
||||
decision.onComplete();
|
||||
|
@ -74,6 +76,10 @@ class IterablePermissionEvaluator implements PermissionEvaluator {
|
|||
return decision;
|
||||
}
|
||||
|
||||
protected Iterator<ResourcePermission> getPermissions() {
|
||||
return this.permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Permission> evaluate(ResourceServer resourceServer, AuthorizationRequest request) {
|
||||
DecisionPermissionCollector decision = new DecisionPermissionCollector(authorizationProvider, resourceServer, request);
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package org.keycloak.authorization.permission.evaluator;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.Decision;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.permission.Permissions;
|
||||
import org.keycloak.authorization.permission.ResourcePermission;
|
||||
import org.keycloak.authorization.policy.evaluation.DecisionPermissionCollector;
|
||||
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
|
||||
import org.keycloak.authorization.policy.evaluation.PolicyEvaluator;
|
||||
import org.keycloak.authorization.store.StoreFactory;
|
||||
import org.keycloak.representations.idm.authorization.AuthorizationRequest;
|
||||
import org.keycloak.representations.idm.authorization.Permission;
|
||||
|
||||
public class UnboundedPermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
private final EvaluationContext executionContext;
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
private final PolicyEvaluator policyEvaluator;
|
||||
private final ResourceServer resourceServer;
|
||||
private final AuthorizationRequest request;
|
||||
|
||||
UnboundedPermissionEvaluator(EvaluationContext executionContext,
|
||||
AuthorizationProvider authorizationProvider, ResourceServer resourceServer,
|
||||
AuthorizationRequest request) {
|
||||
this.executionContext = executionContext;
|
||||
this.authorizationProvider = authorizationProvider;
|
||||
this.policyEvaluator = authorizationProvider.getPolicyEvaluator();
|
||||
this.resourceServer = resourceServer;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Decision evaluate(Decision decision) {
|
||||
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
||||
|
||||
try {
|
||||
Map<Policy, Map<Object, Decision.Effect>> decisionCache = new HashMap<>();
|
||||
|
||||
storeFactory.setReadOnly(true);
|
||||
|
||||
Permissions.all(resourceServer, executionContext.getIdentity(), authorizationProvider, request,
|
||||
permission -> policyEvaluator.evaluate(permission, authorizationProvider, executionContext, decision, decisionCache));
|
||||
|
||||
decision.onComplete();
|
||||
} catch (Throwable cause) {
|
||||
decision.onError(cause);
|
||||
} finally {
|
||||
storeFactory.setReadOnly(false);
|
||||
}
|
||||
|
||||
return decision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Permission> evaluate(ResourceServer resourceServer, AuthorizationRequest request) {
|
||||
DecisionPermissionCollector decision = new DecisionPermissionCollector(authorizationProvider, resourceServer, request);
|
||||
|
||||
evaluate(decision);
|
||||
|
||||
return decision.results();
|
||||
}
|
||||
}
|
|
@ -56,10 +56,13 @@ public class DecisionPermissionCollector extends AbstractDecisionCollector {
|
|||
public void onComplete(Result result) {
|
||||
ResourcePermission permission = result.getPermission();
|
||||
Resource resource = permission.getResource();
|
||||
List<Scope> requestedScopes = permission.getScopes();
|
||||
Collection<Scope> requestedScopes = permission.getScopes();
|
||||
|
||||
if (Effect.PERMIT.equals(result.getEffect())) {
|
||||
grantPermission(authorizationProvider, permissions, permission, resource != null ? resource.getScopes() : requestedScopes, resourceServer, request, result);
|
||||
if (permission.getScopes().isEmpty() && !resource.getScopes().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
grantPermission(authorizationProvider, permissions, permission, requestedScopes, resourceServer, request, result);
|
||||
} else {
|
||||
Set<Scope> grantedScopes = new HashSet<>();
|
||||
Set<Scope> deniedScopes = new HashSet<>();
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
package org.keycloak.authorization.policy.evaluation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -52,11 +52,13 @@ public class DefaultPolicyEvaluator implements PolicyEvaluator {
|
|||
PolicyEnforcementMode enforcementMode = resourceServer.getPolicyEnforcementMode();
|
||||
|
||||
if (PolicyEnforcementMode.DISABLED.equals(enforcementMode)) {
|
||||
DefaultEvaluation evaluation = new DefaultEvaluation(permission, executionContext, decision, authorizationProvider);
|
||||
|
||||
evaluation.grant();
|
||||
|
||||
decision.onComplete(permission);
|
||||
grantAndComplete(permission, authorizationProvider, executionContext, decision);
|
||||
return;
|
||||
}
|
||||
|
||||
// if marked as granted we just complete the evaluation
|
||||
if (permission.isGranted()) {
|
||||
grantAndComplete(permission, authorizationProvider, executionContext, decision);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -78,7 +80,7 @@ public class DefaultPolicyEvaluator implements PolicyEvaluator {
|
|||
}
|
||||
}
|
||||
|
||||
List<Scope> scopes = permission.getScopes();
|
||||
Collection<Scope> scopes = permission.getScopes();
|
||||
|
||||
if (!scopes.isEmpty()) {
|
||||
policyStore.findByScopeIds(scopes.stream().map(Scope::getId).collect(Collectors.toList()), null, resourceServer.getId(), policyConsumer);
|
||||
|
@ -90,12 +92,19 @@ public class DefaultPolicyEvaluator implements PolicyEvaluator {
|
|||
}
|
||||
|
||||
if (PolicyEnforcementMode.PERMISSIVE.equals(enforcementMode)) {
|
||||
DefaultEvaluation evaluation = new DefaultEvaluation(permission, executionContext, decision, authorizationProvider);
|
||||
evaluation.grant();
|
||||
decision.onComplete(permission);
|
||||
grantAndComplete(permission, authorizationProvider, executionContext, decision);
|
||||
}
|
||||
}
|
||||
|
||||
private void grantAndComplete(ResourcePermission permission, AuthorizationProvider authorizationProvider,
|
||||
EvaluationContext executionContext, Decision decision) {
|
||||
DefaultEvaluation evaluation = new DefaultEvaluation(permission, executionContext, decision, authorizationProvider);
|
||||
|
||||
evaluation.grant();
|
||||
|
||||
decision.onComplete(permission);
|
||||
}
|
||||
|
||||
private Consumer<Policy> createPolicyEvaluator(ResourcePermission permission, AuthorizationProvider authorizationProvider, EvaluationContext executionContext, Decision decision, AtomicBoolean verified, Map<Policy, Map<Object, Decision.Effect>> decisionCache) {
|
||||
return parentPolicy -> {
|
||||
PolicyProvider policyProvider = authorizationProvider.getProvider(parentPolicy.getType());
|
||||
|
|
|
@ -116,10 +116,10 @@ public class PermissionTicketAwareDecisionResultCollector extends DecisionPermis
|
|||
filters.put(PermissionTicket.REQUESTER, identity.getId());
|
||||
filters.put(PermissionTicket.SCOPE_IS_NULL, Boolean.TRUE.toString());
|
||||
|
||||
List<PermissionTicket> tickets = authorization.getStoreFactory().getPermissionTicketStore().find(filters, resource.getResourceServer().getId(), -1, -1);
|
||||
List<PermissionTicket> tickets = authorization.getStoreFactory().getPermissionTicketStore().find(filters, resource.getResourceServer(), -1, -1);
|
||||
|
||||
if (tickets.isEmpty()) {
|
||||
authorization.getStoreFactory().getPermissionTicketStore().create(resource.getId(), null, identity.getId(), resource.getResourceServer());
|
||||
authorization.getStoreFactory().getPermissionTicketStore().create(resource.getId(), null, identity.getId(), resourceServer);
|
||||
}
|
||||
} else {
|
||||
ScopeStore scopeStore = authorization.getStoreFactory().getScopeStore();
|
||||
|
@ -137,10 +137,10 @@ public class PermissionTicketAwareDecisionResultCollector extends DecisionPermis
|
|||
filters.put(PermissionTicket.REQUESTER, identity.getId());
|
||||
filters.put(PermissionTicket.SCOPE, scope.getId());
|
||||
|
||||
List<PermissionTicket> tickets = authorization.getStoreFactory().getPermissionTicketStore().find(filters, resource.getResourceServer().getId(), -1, -1);
|
||||
List<PermissionTicket> tickets = authorization.getStoreFactory().getPermissionTicketStore().find(filters, resource.getResourceServer(), -1, -1);
|
||||
|
||||
if (tickets.isEmpty()) {
|
||||
authorization.getStoreFactory().getPermissionTicketStore().create(resource.getId(), scope.getId(), identity.getId(), resource.getResourceServer());
|
||||
authorization.getStoreFactory().getPermissionTicketStore().create(resource.getId(), scope.getId(), identity.getId(), resourceServer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,14 @@ public class Result {
|
|||
}
|
||||
|
||||
public PolicyResult policy(Policy policy) {
|
||||
return results.computeIfAbsent(policy.getId(), id -> new PolicyResult(policy));
|
||||
PolicyResult result = results.get(policy.getId());
|
||||
|
||||
if (result == null) {
|
||||
result = new PolicyResult(policy);
|
||||
results.put(policy.getId(), result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setStatus(final Effect status) {
|
||||
|
|
|
@ -943,11 +943,11 @@ public class ModelToRepresentation {
|
|||
return representation;
|
||||
}
|
||||
|
||||
public static ResourceRepresentation toRepresentation(Resource model, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
||||
public static ResourceRepresentation toRepresentation(Resource model, String resourceServer, AuthorizationProvider authorization) {
|
||||
return toRepresentation(model, resourceServer, authorization, true);
|
||||
}
|
||||
|
||||
public static ResourceRepresentation toRepresentation(Resource model, ResourceServer resourceServer, AuthorizationProvider authorization, Boolean deep) {
|
||||
public static ResourceRepresentation toRepresentation(Resource model, String resourceServer, AuthorizationProvider authorization, Boolean deep) {
|
||||
ResourceRepresentation resource = new ResourceRepresentation();
|
||||
|
||||
resource.setId(model.getId());
|
||||
|
@ -965,8 +965,8 @@ public class ModelToRepresentation {
|
|||
KeycloakSession keycloakSession = authorization.getKeycloakSession();
|
||||
RealmModel realm = authorization.getRealm();
|
||||
|
||||
if (owner.getId().equals(resourceServer.getId())) {
|
||||
ClientModel clientModel = realm.getClientById(resourceServer.getId());
|
||||
if (owner.getId().equals(resourceServer)) {
|
||||
ClientModel clientModel = realm.getClientById(resourceServer);
|
||||
owner.setName(clientModel.getClientId());
|
||||
} else {
|
||||
UserModel userModel = keycloakSession.users().getUserById(owner.getId(), realm);
|
||||
|
|
|
@ -47,13 +47,13 @@ import org.keycloak.authorization.common.KeycloakIdentity;
|
|||
import org.keycloak.authorization.model.Resource;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.model.Scope;
|
||||
import org.keycloak.authorization.permission.Permissions;
|
||||
import org.keycloak.authorization.permission.ResourcePermission;
|
||||
import org.keycloak.authorization.policy.evaluation.DecisionPermissionCollector;
|
||||
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
|
||||
import org.keycloak.authorization.policy.evaluation.Result;
|
||||
import org.keycloak.authorization.store.ScopeStore;
|
||||
import org.keycloak.authorization.store.StoreFactory;
|
||||
import org.keycloak.authorization.util.Permissions;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientSessionContext;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
@ -125,7 +125,13 @@ public class PolicyEvaluationService {
|
|||
}
|
||||
|
||||
private EvaluationDecisionCollector evaluate(PolicyEvaluationRequest evaluationRequest, EvaluationContext evaluationContext, AuthorizationRequest request) {
|
||||
return authorization.evaluators().from(createPermissions(evaluationRequest, evaluationContext, authorization, request), evaluationContext).evaluate(new EvaluationDecisionCollector(authorization, resourceServer, request));
|
||||
List<ResourcePermission> permissions = createPermissions(evaluationRequest, evaluationContext, authorization, request);
|
||||
|
||||
if (permissions.isEmpty()) {
|
||||
return authorization.evaluators().from(evaluationContext, resourceServer, request).evaluate(new EvaluationDecisionCollector(authorization, resourceServer, request));
|
||||
}
|
||||
|
||||
return authorization.evaluators().from(permissions, evaluationContext).evaluate(new EvaluationDecisionCollector(authorization, resourceServer, request));
|
||||
}
|
||||
|
||||
private EvaluationContext createEvaluationContext(PolicyEvaluationRequest representation, KeycloakIdentity identity) {
|
||||
|
@ -170,12 +176,14 @@ public class PolicyEvaluationService {
|
|||
|
||||
if (resource.getId() != null) {
|
||||
Resource resourceModel = storeFactory.getResourceStore().findById(resource.getId(), resourceServer.getId());
|
||||
return new ArrayList<>(Arrays.asList(Permissions.createResourcePermissions(resourceModel, scopes, authorization, request))).stream();
|
||||
return new ArrayList<>(Arrays.asList(
|
||||
Permissions.createResourcePermissions(resourceModel, resourceServer, scopes, authorization, request))).stream();
|
||||
} else if (resource.getType() != null) {
|
||||
return storeFactory.getResourceStore().findByType(resource.getType(), resourceServer.getId()).stream().map(resource1 -> Permissions.createResourcePermissions(resource1, scopes, authorization, request));
|
||||
return storeFactory.getResourceStore().findByType(resource.getType(), resourceServer.getId()).stream().map(resource1 -> Permissions.createResourcePermissions(resource1,
|
||||
resourceServer, scopes, authorization, request));
|
||||
} else {
|
||||
if (scopes.isEmpty()) {
|
||||
return Permissions.all(resourceServer, evaluationContext.getIdentity(), authorization, request).stream();
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
List<Resource> resources = storeFactory.getResourceStore().findByScope(scopes.stream().map(Scope::getId).collect(Collectors.toList()), resourceServer.getId());
|
||||
|
@ -185,7 +193,8 @@ public class PolicyEvaluationService {
|
|||
}
|
||||
|
||||
|
||||
return resources.stream().map(resource12 -> Permissions.createResourcePermissions(resource12, scopes, authorization, request));
|
||||
return resources.stream().map(resource12 -> Permissions.createResourcePermissions(resource12, resourceServer,
|
||||
scopes, authorization, request));
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ public class ResourceSetService {
|
|||
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "Resource with name [" + resource.getName() + "] already exists.", Status.CONFLICT);
|
||||
}
|
||||
|
||||
return toRepresentation(toModel(resource, this.resourceServer, authorization), resourceServer, authorization);
|
||||
return toRepresentation(toModel(resource, this.resourceServer, authorization), resourceServer.getId(), authorization);
|
||||
}
|
||||
|
||||
@Path("{id}")
|
||||
|
@ -166,7 +166,7 @@ public class ResourceSetService {
|
|||
|
||||
storeFactory.getResourceStore().delete(id);
|
||||
|
||||
audit(toRepresentation(resource, resourceServer, authorization), OperationType.DELETE);
|
||||
audit(toRepresentation(resource, resourceServer.getId(), authorization), OperationType.DELETE);
|
||||
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ public class ResourceSetService {
|
|||
@NoCache
|
||||
@Produces("application/json")
|
||||
public Response findById(@PathParam("id") String id) {
|
||||
return findById(id, resource -> toRepresentation(resource, resourceServer, authorization, true));
|
||||
return findById(id, resource -> toRepresentation(resource, resourceServer.getId(), authorization, true));
|
||||
}
|
||||
|
||||
public Response findById(String id, Function<Resource, ? extends ResourceRepresentation> toRepresentation) {
|
||||
|
@ -322,7 +322,7 @@ public class ResourceSetService {
|
|||
return Response.status(Status.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
return Response.ok(toRepresentation(model, this.resourceServer, authorization)).build();
|
||||
return Response.ok(toRepresentation(model, this.resourceServer.getId(), authorization)).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
|
@ -339,7 +339,7 @@ public class ResourceSetService {
|
|||
@QueryParam("deep") Boolean deep,
|
||||
@QueryParam("first") Integer firstResult,
|
||||
@QueryParam("max") Integer maxResult) {
|
||||
return find(id, name, uri, owner, type, scope, matchingUri, exactName, deep, firstResult, maxResult, (BiFunction<Resource, Boolean, ResourceRepresentation>) (resource, deep1) -> toRepresentation(resource, resourceServer, authorization, deep1));
|
||||
return find(id, name, uri, owner, type, scope, matchingUri, exactName, deep, firstResult, maxResult, (BiFunction<Resource, Boolean, ResourceRepresentation>) (resource, deep1) -> toRepresentation(resource, resourceServer.getId(), authorization, deep1));
|
||||
}
|
||||
|
||||
public Response find(@QueryParam("_id") String id,
|
||||
|
|
|
@ -19,7 +19,6 @@ package org.keycloak.authorization.authorization;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
|
@ -48,6 +47,7 @@ import org.keycloak.authorization.model.Resource;
|
|||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.model.Scope;
|
||||
import org.keycloak.authorization.model.PermissionTicket;
|
||||
import org.keycloak.authorization.permission.Permissions;
|
||||
import org.keycloak.authorization.permission.ResourcePermission;
|
||||
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
|
||||
import org.keycloak.authorization.policy.evaluation.PermissionTicketAwareDecisionResultCollector;
|
||||
|
@ -55,7 +55,6 @@ import org.keycloak.authorization.store.ResourceServerStore;
|
|||
import org.keycloak.authorization.store.ResourceStore;
|
||||
import org.keycloak.authorization.store.ScopeStore;
|
||||
import org.keycloak.authorization.store.StoreFactory;
|
||||
import org.keycloak.authorization.util.Permissions;
|
||||
import org.keycloak.authorization.util.Tokens;
|
||||
import org.keycloak.common.util.Base64Url;
|
||||
import org.keycloak.events.Details;
|
||||
|
@ -197,9 +196,9 @@ public class AuthorizationTokenService {
|
|||
Collection<Permission> permissions;
|
||||
|
||||
if (request.getTicket() != null) {
|
||||
permissions = evaluateUserManagedPermissions(request, ticket, resourceServer, evaluationContext, identity);
|
||||
permissions = evaluateUserManagedPermissions(request, ticket, resourceServer, evaluationContext);
|
||||
} else if (ticket.getPermissions().isEmpty() && request.getRpt() == null) {
|
||||
permissions = evaluateAllPermissions(request, resourceServer, evaluationContext, identity);
|
||||
permissions = evaluateAllPermissions(request, resourceServer, evaluationContext);
|
||||
} else {
|
||||
permissions = evaluatePermissions(request, ticket, resourceServer, evaluationContext, identity);
|
||||
}
|
||||
|
@ -257,21 +256,21 @@ public class AuthorizationTokenService {
|
|||
private Collection<Permission> evaluatePermissions(KeycloakAuthorizationRequest request, PermissionTicketToken ticket, ResourceServer resourceServer, EvaluationContext evaluationContext, KeycloakIdentity identity) {
|
||||
AuthorizationProvider authorization = request.getAuthorization();
|
||||
return authorization.evaluators()
|
||||
.from(createPermissions(ticket, request, resourceServer, identity, authorization), evaluationContext)
|
||||
.from(createPermissions(ticket, request, resourceServer, authorization, evaluationContext), evaluationContext)
|
||||
.evaluate(resourceServer, request);
|
||||
}
|
||||
|
||||
private Collection<Permission> evaluateUserManagedPermissions(KeycloakAuthorizationRequest request, PermissionTicketToken ticket, ResourceServer resourceServer, EvaluationContext evaluationContext, KeycloakIdentity identity) {
|
||||
private Collection<Permission> evaluateUserManagedPermissions(KeycloakAuthorizationRequest request, PermissionTicketToken ticket, ResourceServer resourceServer, EvaluationContext evaluationContext) {
|
||||
AuthorizationProvider authorization = request.getAuthorization();
|
||||
return authorization.evaluators()
|
||||
.from(createPermissions(ticket, request, resourceServer, identity, authorization), evaluationContext)
|
||||
.evaluate(new PermissionTicketAwareDecisionResultCollector(request, ticket, identity, resourceServer, authorization)).results();
|
||||
.from(createPermissions(ticket, request, resourceServer, authorization, evaluationContext), evaluationContext)
|
||||
.evaluate(new PermissionTicketAwareDecisionResultCollector(request, ticket, evaluationContext.getIdentity(), resourceServer, authorization)).results();
|
||||
}
|
||||
|
||||
private Collection<Permission> evaluateAllPermissions(KeycloakAuthorizationRequest request, ResourceServer resourceServer, EvaluationContext evaluationContext, KeycloakIdentity identity) {
|
||||
private Collection<Permission> evaluateAllPermissions(KeycloakAuthorizationRequest request, ResourceServer resourceServer, EvaluationContext evaluationContext) {
|
||||
AuthorizationProvider authorization = request.getAuthorization();
|
||||
return authorization.evaluators()
|
||||
.from(Permissions.all(resourceServer, identity, authorization, request), evaluationContext)
|
||||
.from(evaluationContext, resourceServer, request)
|
||||
.evaluate(resourceServer, request);
|
||||
}
|
||||
|
||||
|
@ -419,7 +418,8 @@ public class AuthorizationTokenService {
|
|||
return evaluationContextProvider.apply(request, request.getAuthorization());
|
||||
}
|
||||
|
||||
private Collection<ResourcePermission> createPermissions(PermissionTicketToken ticket, KeycloakAuthorizationRequest request, ResourceServer resourceServer, KeycloakIdentity identity, AuthorizationProvider authorization) {
|
||||
private Collection<ResourcePermission> createPermissions(PermissionTicketToken ticket, KeycloakAuthorizationRequest request, ResourceServer resourceServer, AuthorizationProvider authorization, EvaluationContext context) {
|
||||
KeycloakIdentity identity = (KeycloakIdentity) context.getIdentity();
|
||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||
Map<String, ResourcePermission> permissionsToEvaluate = new LinkedHashMap<>();
|
||||
ResourceStore resourceStore = storeFactory.getResourceStore();
|
||||
|
@ -432,145 +432,32 @@ public class AuthorizationTokenService {
|
|||
break;
|
||||
}
|
||||
|
||||
Set<String> requestedScopes = permission.getScopes();
|
||||
|
||||
if (permission.getScopes() == null) {
|
||||
requestedScopes = new HashSet<>();
|
||||
}
|
||||
|
||||
List<Resource> requestedResources = new ArrayList<>();
|
||||
Set<Scope> requestedScopesModel = resolveRequestedScopes(request, resourceServer, scopeStore, permission);
|
||||
String resourceId = permission.getResourceId();
|
||||
|
||||
if (resourceId != null) {
|
||||
Resource resource = null;
|
||||
|
||||
if (resourceId.indexOf('-') != -1) {
|
||||
resource = resourceStore.findById(resourceId, resourceServer.getId());
|
||||
}
|
||||
|
||||
if (resource != null) {
|
||||
requestedResources.add(resource);
|
||||
} else if (resourceId.startsWith("resource-type:")) {
|
||||
// only resource types, no resource instances. resource types are owned by the resource server
|
||||
String resourceType = resourceId.substring("resource-type:".length());
|
||||
resourceStore.findByType(resourceType, resourceServer.getId(), resourceServer.getId(), requestedResources::add);
|
||||
} else if (resourceId.startsWith("resource-type-any:")) {
|
||||
// any resource with a given type
|
||||
String resourceType = resourceId.substring("resource-type-any:".length());
|
||||
resourceStore.findByType(resourceType, null, resourceServer.getId(), requestedResources::add);
|
||||
} else if (resourceId.startsWith("resource-type-instance:")) {
|
||||
// only resource instances with a given type
|
||||
String resourceType = resourceId.substring("resource-type-instance:".length());
|
||||
resourceStore.findByTypeInstance(resourceType, resourceServer.getId(), requestedResources::add);
|
||||
} else if (resourceId.startsWith("resource-type-owner:")) {
|
||||
// only resources where the current identity is the owner
|
||||
String resourceType = resourceId.substring("resource-type-owner:".length());
|
||||
resourceStore.findByType(resourceType, identity.getId(), resourceServer.getId(), requestedResources::add);
|
||||
} else {
|
||||
String resourceName = resourceId;
|
||||
Resource ownerResource = resourceStore.findByName(resourceName, identity.getId(), resourceServer.getId());
|
||||
|
||||
if (ownerResource != null) {
|
||||
permission.setResourceId(ownerResource.getId());
|
||||
requestedResources.add(ownerResource);
|
||||
}
|
||||
|
||||
if (!identity.isResourceServer() || !identity.getId().equals(resourceServer.getId())) {
|
||||
List<PermissionTicket> tickets = storeFactory.getPermissionTicketStore().findGranted(resourceName, identity.getId(), resourceServer.getId());
|
||||
for (PermissionTicket permissionTicket : tickets) {
|
||||
requestedResources.add(permissionTicket.getResource());
|
||||
}
|
||||
|
||||
Resource serverResource = resourceStore.findByName(resourceName, resourceServer.getId());
|
||||
|
||||
if (serverResource != null) {
|
||||
permission.setResourceId(serverResource.getId());
|
||||
requestedResources.add(serverResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String clientAdditionalScopes = request.getScope();
|
||||
|
||||
if (clientAdditionalScopes != null) {
|
||||
requestedScopes.addAll(Arrays.asList(clientAdditionalScopes.split(" ")));
|
||||
}
|
||||
|
||||
Set<Scope> requestedScopesModel = requestedScopes.stream().map(s -> scopeStore.findByName(s, resourceServer.getId())).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
|
||||
if (resourceId != null && requestedResources.isEmpty()) {
|
||||
throw new CorsErrorResponseException(request.getCors(), "invalid_resource", "Resource with id [" + resourceId + "] does not exist.", Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (!requestedScopes.isEmpty() && requestedScopesModel.isEmpty()) {
|
||||
throw new CorsErrorResponseException(request.getCors(), "invalid_scope", "One of the given scopes " + permission.getScopes() + " is invalid", Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (!requestedResources.isEmpty()) {
|
||||
for (Resource resource : requestedResources) {
|
||||
if (limit != null && limit.get() <= 0) {
|
||||
break;
|
||||
}
|
||||
ResourcePermission perm = permissionsToEvaluate.get(resource.getId());
|
||||
|
||||
if (perm == null) {
|
||||
perm = Permissions.createResourcePermissions(resource, requestedScopesModel, authorization, request);
|
||||
//if scopes were requested, check if the permission to evaluate resolves to any of the requested scopes.
|
||||
// if it is not the case, then the requested scope is invalid and we don't need to evaluate
|
||||
if (!requestedScopesModel.isEmpty() && perm.getScopes().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
permissionsToEvaluate.put(resource.getId(), perm);
|
||||
if (limit != null) {
|
||||
limit.decrementAndGet();
|
||||
}
|
||||
} else {
|
||||
for (Scope scope : requestedScopesModel) {
|
||||
perm.addScope(scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
resolveResourcePermission(request, resourceServer, identity, authorization, storeFactory, permissionsToEvaluate,
|
||||
resourceStore,
|
||||
limit, permission, requestedScopesModel, resourceId);
|
||||
} else {
|
||||
AtomicBoolean processed = new AtomicBoolean();
|
||||
|
||||
resourceStore.findByScope(requestedScopesModel.stream().map(Scope::getId).collect(Collectors.toList()), resourceServer.getId(), resource -> {
|
||||
if (limit != null && limit.get() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResourcePermission perm = permissionsToEvaluate.get(resource.getId());
|
||||
|
||||
if (perm == null) {
|
||||
perm = Permissions.createResourcePermissions(resource, requestedScopesModel, authorization, request);
|
||||
permissionsToEvaluate.put(resource.getId(), perm);
|
||||
if (limit != null) {
|
||||
limit.decrementAndGet();
|
||||
}
|
||||
} else {
|
||||
for (Scope scope : requestedScopesModel) {
|
||||
perm.addScope(scope);
|
||||
}
|
||||
}
|
||||
|
||||
processed.compareAndSet(false, true);
|
||||
});
|
||||
|
||||
if (!processed.get()) {
|
||||
for (Scope scope : requestedScopesModel) {
|
||||
if (limit != null && limit.getAndDecrement() <= 0) {
|
||||
break;
|
||||
}
|
||||
permissionsToEvaluate.computeIfAbsent(scope.getId(), s -> new ResourcePermission(null, new ArrayList<>(Arrays.asList(scope)), resourceServer, request.getClaims()));
|
||||
}
|
||||
}
|
||||
resolveScopePermissions(request, resourceServer, authorization, permissionsToEvaluate, resourceStore, limit,
|
||||
requestedScopesModel);
|
||||
}
|
||||
}
|
||||
|
||||
resolvePreviousGrantedPermissions(ticket, request, resourceServer, permissionsToEvaluate, resourceStore, scopeStore, limit);
|
||||
|
||||
return permissionsToEvaluate.values();
|
||||
}
|
||||
|
||||
private void resolvePreviousGrantedPermissions(PermissionTicketToken ticket,
|
||||
KeycloakAuthorizationRequest request, ResourceServer resourceServer,
|
||||
Map<String, ResourcePermission> permissionsToEvaluate, ResourceStore resourceStore, ScopeStore scopeStore,
|
||||
AtomicInteger limit) {
|
||||
AccessToken rpt = request.getRpt();
|
||||
|
||||
if (rpt != null && rpt.isActive()) {
|
||||
AccessToken.Authorization authorizationData = rpt.getAuthorization();
|
||||
Authorization authorizationData = rpt.getAuthorization();
|
||||
|
||||
if (authorizationData != null) {
|
||||
Collection<Permission> permissions = authorizationData.getPermissions();
|
||||
|
@ -618,8 +505,166 @@ public class AuthorizationTokenService {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return permissionsToEvaluate.values();
|
||||
private void resolveScopePermissions(KeycloakAuthorizationRequest request,
|
||||
ResourceServer resourceServer, AuthorizationProvider authorization,
|
||||
Map<String, ResourcePermission> permissionsToEvaluate, ResourceStore resourceStore, AtomicInteger limit,
|
||||
Set<Scope> requestedScopesModel) {
|
||||
AtomicBoolean processed = new AtomicBoolean();
|
||||
|
||||
resourceStore.findByScope(requestedScopesModel.stream().map(Scope::getId).collect(Collectors.toList()), resourceServer.getId(), resource -> {
|
||||
if (limit != null && limit.get() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResourcePermission perm = permissionsToEvaluate.get(resource.getId());
|
||||
|
||||
if (perm == null) {
|
||||
perm = Permissions.createResourcePermissions(resource, resourceServer, requestedScopesModel, authorization, request);
|
||||
permissionsToEvaluate.put(resource.getId(), perm);
|
||||
if (limit != null) {
|
||||
limit.decrementAndGet();
|
||||
}
|
||||
} else {
|
||||
for (Scope scope : requestedScopesModel) {
|
||||
perm.addScope(scope);
|
||||
}
|
||||
}
|
||||
|
||||
processed.compareAndSet(false, true);
|
||||
});
|
||||
|
||||
if (!processed.get()) {
|
||||
for (Scope scope : requestedScopesModel) {
|
||||
if (limit != null && limit.getAndDecrement() <= 0) {
|
||||
break;
|
||||
}
|
||||
permissionsToEvaluate.computeIfAbsent(scope.getId(), s -> new ResourcePermission(null, new ArrayList<>(Arrays.asList(scope)), resourceServer, request.getClaims()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveResourcePermission(KeycloakAuthorizationRequest request,
|
||||
ResourceServer resourceServer, KeycloakIdentity identity, AuthorizationProvider authorization,
|
||||
StoreFactory storeFactory, Map<String, ResourcePermission> permissionsToEvaluate, ResourceStore resourceStore,
|
||||
AtomicInteger limit, Permission permission, Set<Scope> requestedScopesModel, String resourceId) {
|
||||
Resource resource;
|
||||
|
||||
if (resourceId.indexOf('-') != -1) {
|
||||
resource = resourceStore.findById(resourceId, resourceServer.getId());
|
||||
} else {
|
||||
resource = null;
|
||||
}
|
||||
|
||||
if (resource != null) {
|
||||
addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, resource);
|
||||
} else if (resourceId.startsWith("resource-type:")) {
|
||||
// only resource types, no resource instances. resource types are owned by the resource server
|
||||
String resourceType = resourceId.substring("resource-type:".length());
|
||||
resourceStore.findByType(resourceType, resourceServer.getId(), resourceServer.getId(),
|
||||
resource1 -> addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, resource1));
|
||||
} else if (resourceId.startsWith("resource-type-any:")) {
|
||||
// any resource with a given type
|
||||
String resourceType = resourceId.substring("resource-type-any:".length());
|
||||
resourceStore.findByType(resourceType, null, resourceServer.getId(),
|
||||
resource12 -> addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, resource12));
|
||||
} else if (resourceId.startsWith("resource-type-instance:")) {
|
||||
// only resource instances with a given type
|
||||
String resourceType = resourceId.substring("resource-type-instance:".length());
|
||||
resourceStore.findByTypeInstance(resourceType, resourceServer.getId(),
|
||||
resource13 -> addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, resource13));
|
||||
} else if (resourceId.startsWith("resource-type-owner:")) {
|
||||
// only resources where the current identity is the owner
|
||||
String resourceType = resourceId.substring("resource-type-owner:".length());
|
||||
resourceStore.findByType(resourceType, identity.getId(), resourceServer.getId(),
|
||||
resource14 -> addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, resource14));
|
||||
} else {
|
||||
Resource ownerResource = resourceStore.findByName(resourceId, identity.getId(), resourceServer.getId());
|
||||
|
||||
if (ownerResource != null) {
|
||||
permission.setResourceId(ownerResource.getId());
|
||||
addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, ownerResource);
|
||||
}
|
||||
|
||||
if (!identity.isResourceServer() || !identity.getId().equals(resourceServer.getId())) {
|
||||
List<PermissionTicket> tickets = storeFactory.getPermissionTicketStore().findGranted(resourceId, identity.getId(), resourceServer.getId());
|
||||
|
||||
if (!tickets.isEmpty()) {
|
||||
List<Scope> scopes = new ArrayList<>();
|
||||
Resource grantedResource = null;
|
||||
for (PermissionTicket permissionTicket : tickets) {
|
||||
if (grantedResource == null) {
|
||||
grantedResource = permissionTicket.getResource();
|
||||
}
|
||||
scopes.add(permissionTicket.getScope());
|
||||
}
|
||||
requestedScopesModel.retainAll(scopes);
|
||||
ResourcePermission resourcePermission = addPermission(request, resourceServer, authorization,
|
||||
permissionsToEvaluate, limit,
|
||||
requestedScopesModel, grantedResource);
|
||||
|
||||
// the permission is explicitly granted by the owner, mark this permission as granted so that we don't run the evaluation engine on it
|
||||
resourcePermission.setGranted(true);
|
||||
}
|
||||
|
||||
Resource serverResource = resourceStore.findByName(resourceId, resourceServer.getId());
|
||||
|
||||
if (serverResource != null) {
|
||||
permission.setResourceId(serverResource.getId());
|
||||
addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, serverResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (permissionsToEvaluate.isEmpty()) {
|
||||
throw new CorsErrorResponseException(request.getCors(), "invalid_resource", "Resource with id [" + resourceId + "] does not exist.", Status.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Scope> resolveRequestedScopes(KeycloakAuthorizationRequest request,
|
||||
ResourceServer resourceServer, ScopeStore scopeStore, Permission permission) {
|
||||
String clientAdditionalScopes = request.getScope();
|
||||
Set<String> requestedScopes = permission.getScopes();
|
||||
|
||||
if (permission.getScopes() == null) {
|
||||
requestedScopes = new HashSet<>();
|
||||
}
|
||||
|
||||
if (clientAdditionalScopes != null) {
|
||||
requestedScopes.addAll(Arrays.asList(clientAdditionalScopes.split(" ")));
|
||||
}
|
||||
|
||||
Set<Scope> requestedScopesModel = requestedScopes.stream().map(s -> scopeStore.findByName(s, resourceServer.getId())).filter(
|
||||
Objects::nonNull).collect(Collectors.toSet());
|
||||
|
||||
if (!requestedScopes.isEmpty() && requestedScopesModel.isEmpty()) {
|
||||
throw new CorsErrorResponseException(request.getCors(), "invalid_scope", "One of the given scopes " + permission.getScopes() + " is invalid", Status.BAD_REQUEST);
|
||||
}
|
||||
return requestedScopesModel;
|
||||
}
|
||||
|
||||
private ResourcePermission addPermission(KeycloakAuthorizationRequest request, ResourceServer resourceServer,
|
||||
AuthorizationProvider authorization, Map<String, ResourcePermission> permissionsToEvaluate, AtomicInteger limit,
|
||||
Set<Scope> requestedScopesModel, Resource resource) {
|
||||
ResourcePermission permission = permissionsToEvaluate.get(resource.getId());
|
||||
|
||||
if (permission == null) {
|
||||
permission = new ResourcePermission(resource,
|
||||
Permissions.resolveScopes(resource, resourceServer, requestedScopesModel, authorization), resourceServer,
|
||||
request.getClaims());
|
||||
//if scopes were requested, check if the permission to evaluate resolves to any of the requested scopes.
|
||||
// if it is not the case, then the requested scope is invalid and we don't need to evaluate
|
||||
if (!requestedScopesModel.isEmpty() && permission.getScopes().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
permissionsToEvaluate.put(resource.getId(), permission);
|
||||
if (limit != null) {
|
||||
limit.decrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
return permission;
|
||||
}
|
||||
|
||||
private PermissionTicketToken verifyPermissionTicket(KeycloakAuthorizationRequest request) {
|
||||
|
|
|
@ -128,7 +128,7 @@ public class AbstractPermissionService {
|
|||
|
||||
if (scope == null && resource.getType() != null) {
|
||||
scope = resourceStore.findByType(resource.getType(), resourceServer.getId()).stream()
|
||||
.filter(baseResource -> baseResource.getOwner().equals(resource.getResourceServer().getId()))
|
||||
.filter(baseResource -> baseResource.getOwner().equals(resource.getResourceServer()))
|
||||
.flatMap(resource1 -> resource1.getScopes().stream())
|
||||
.filter(baseScope -> baseScope.getName().equals(scopeName)).findFirst().orElse(null);
|
||||
}
|
||||
|
|
|
@ -334,7 +334,7 @@ public class ExportUtils {
|
|||
|
||||
List<ResourceRepresentation> resources = storeFactory.getResourceStore().findByResourceServer(settingsModel.getId())
|
||||
.stream().map(resource -> {
|
||||
ResourceRepresentation rep = toRepresentation(resource, settingsModel, authorization);
|
||||
ResourceRepresentation rep = toRepresentation(resource, settingsModel.getId(), authorization);
|
||||
|
||||
if (rep.getOwner().getId().equals(settingsModel.getId())) {
|
||||
rep.setOwner((ResourceOwnerRepresentation) null);
|
||||
|
|
|
@ -234,7 +234,7 @@ public class AuthorizationBean {
|
|||
|
||||
public ResourceBean(Resource resource) {
|
||||
RealmModel realm = authorization.getRealm();
|
||||
resourceServer = new ResourceServerBean(realm.getClientById(resource.getResourceServer().getId()));
|
||||
resourceServer = new ResourceServerBean(realm.getClientById(resource.getResourceServer()));
|
||||
this.resource = resource;
|
||||
userOwner = authorization.getKeycloakSession().users().getUserById(resource.getOwner(), realm);
|
||||
if (userOwner == null) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.keycloak.authorization.AuthorizationProvider;
|
|||
import org.keycloak.authorization.model.PermissionTicket;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.Resource;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.model.Scope;
|
||||
import org.keycloak.authorization.store.PermissionTicketStore;
|
||||
import org.keycloak.authorization.store.PolicyStore;
|
||||
|
@ -822,7 +823,7 @@ public class AccountFormService extends AbstractSecuredLocalService {
|
|||
filters.put(PermissionTicket.GRANTED, Boolean.FALSE.toString());
|
||||
}
|
||||
|
||||
List<PermissionTicket> tickets = ticketStore.find(filters, resource.getResourceServer().getId(), -1, -1);
|
||||
List<PermissionTicket> tickets = ticketStore.find(filters, resource.getResourceServer(), -1, -1);
|
||||
Iterator<PermissionTicket> iterator = tickets.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
|
@ -876,6 +877,7 @@ public class AccountFormService extends AbstractSecuredLocalService {
|
|||
AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
|
||||
PermissionTicketStore ticketStore = authorization.getStoreFactory().getPermissionTicketStore();
|
||||
Resource resource = authorization.getStoreFactory().getResourceStore().findById(resourceId, null);
|
||||
ResourceServer resourceServer = authorization.getStoreFactory().getResourceServerStore().findById(resource.getResourceServer());
|
||||
|
||||
if (resource == null) {
|
||||
return ErrorResponse.error("Invalid resource", Response.Status.BAD_REQUEST);
|
||||
|
@ -908,21 +910,21 @@ public class AccountFormService extends AbstractSecuredLocalService {
|
|||
filters.put(PermissionTicket.OWNER, auth.getUser().getId());
|
||||
filters.put(PermissionTicket.REQUESTER, user.getId());
|
||||
|
||||
List<PermissionTicket> tickets = ticketStore.find(filters, resource.getResourceServer().getId(), -1, -1);
|
||||
List<PermissionTicket> tickets = ticketStore.find(filters, resource.getResourceServer(), -1, -1);
|
||||
|
||||
if (tickets.isEmpty()) {
|
||||
if (scopes != null && scopes.length > 0) {
|
||||
for (String scope : scopes) {
|
||||
PermissionTicket ticket = ticketStore.create(resourceId, scope, user.getId(), resource.getResourceServer());
|
||||
PermissionTicket ticket = ticketStore.create(resourceId, scope, user.getId(), resourceServer);
|
||||
ticket.setGrantedTimestamp(System.currentTimeMillis());
|
||||
}
|
||||
} else {
|
||||
if (resource.getScopes().isEmpty()) {
|
||||
PermissionTicket ticket = ticketStore.create(resourceId, null, user.getId(), resource.getResourceServer());
|
||||
PermissionTicket ticket = ticketStore.create(resourceId, null, user.getId(), resourceServer);
|
||||
ticket.setGrantedTimestamp(System.currentTimeMillis());
|
||||
} else {
|
||||
for (Scope scope : resource.getScopes()) {
|
||||
PermissionTicket ticket = ticketStore.create(resourceId, scope.getId(), user.getId(), resource.getResourceServer());
|
||||
PermissionTicket ticket = ticketStore.create(resourceId, scope.getId(), user.getId(), resourceServer);
|
||||
ticket.setGrantedTimestamp(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
@ -939,7 +941,7 @@ public class AccountFormService extends AbstractSecuredLocalService {
|
|||
}
|
||||
|
||||
for (String grantScope : grantScopes) {
|
||||
PermissionTicket ticket = ticketStore.create(resourceId, grantScope, user.getId(), resource.getResourceServer());
|
||||
PermissionTicket ticket = ticketStore.create(resourceId, grantScope, user.getId(), resourceServer);
|
||||
ticket.setGrantedTimestamp(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
@ -983,7 +985,7 @@ public class AccountFormService extends AbstractSecuredLocalService {
|
|||
filters.put(PermissionTicket.GRANTED, Boolean.FALSE.toString());
|
||||
}
|
||||
|
||||
for (PermissionTicket ticket : ticketStore.find(filters, resource.getResourceServer().getId(), -1, -1)) {
|
||||
for (PermissionTicket ticket : ticketStore.find(filters, resource.getResourceServer(), -1, -1)) {
|
||||
ticketStore.delete(ticket.getId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,8 +89,7 @@ public abstract class AbstractResourceService {
|
|||
|
||||
setScopes(resource.getScopes().stream().map(Scope::new).collect(Collectors.toSet()));
|
||||
|
||||
ResourceServer resourceServer = resource.getResourceServer();
|
||||
this.client = new Client(provider.getRealm().getClientById(resourceServer.getId()));
|
||||
this.client = new Client(provider.getRealm().getClientById(resource.getResourceServer()));
|
||||
}
|
||||
|
||||
Resource(org.keycloak.authorization.model.Resource resource, AuthorizationProvider provider) {
|
||||
|
|
|
@ -56,7 +56,7 @@ public class ResourceService extends AbstractResourceService {
|
|||
Auth auth, HttpRequest request) {
|
||||
super(session, user, auth, request);
|
||||
this.resource = resource;
|
||||
this.resourceServer = resource.getResourceServer();
|
||||
this.resourceServer = provider.getStoreFactory().getResourceServerStore().findById(resource.getResourceServer());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +122,6 @@ public class ResourceService extends AbstractResourceService {
|
|||
throw new BadRequestException("invalid_permissions");
|
||||
}
|
||||
|
||||
ResourceServer resourceServer = resource.getResourceServer();
|
||||
Map<String, String> filters = new HashMap<>();
|
||||
|
||||
filters.put(PermissionTicket.RESOURCE, resource.getId());
|
||||
|
@ -132,7 +131,7 @@ public class ResourceService extends AbstractResourceService {
|
|||
|
||||
filters.put(PermissionTicket.REQUESTER, user.getId());
|
||||
|
||||
List<PermissionTicket> tickets = ticketStore.find(filters, resource.getResourceServer().getId(), -1, -1);
|
||||
List<PermissionTicket> tickets = ticketStore.find(filters, resource.getResourceServer(), -1, -1);
|
||||
|
||||
// grants all requested permissions
|
||||
if (tickets.isEmpty()) {
|
||||
|
|
Loading…
Reference in a new issue