[KEYCLOAK-12735] - Improving queries and cache for authz
This commit is contained in:
parent
874642fe9e
commit
601bf8d63e
6 changed files with 30 additions and 29 deletions
|
@ -56,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 fetch p.resources r left join fetch p.scopes s inner join fetch p.associatedPolicies a where p.resourceServer.id = :serverId and (r.resourceServer.id = :serverId and r.id = :resourceId)"),
|
||||
@NamedQuery(name="findPolicyIdByScope", query="select pe from PolicyEntity pe left join fetch pe.resources r inner join fetch 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 fetch pe.resources r inner join fetch 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.resources r inner join fetch 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"),
|
||||
@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="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 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"),
|
||||
@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)"),
|
||||
|
|
|
@ -57,10 +57,10 @@ import org.hibernate.annotations.FetchMode;
|
|||
})
|
||||
@NamedQueries(
|
||||
{
|
||||
@NamedQuery(name="findResourceIdByOwner", query="select distinct(r) from ResourceEntity r left join fetch r.scopes s where r.resourceServer.id = :serverId and r.owner = :owner"),
|
||||
@NamedQuery(name="findResourceIdByOwnerOrdered", query="select distinct(r) from ResourceEntity r left join fetch r.scopes s where r.resourceServer.id = :serverId and r.owner = :owner order by r.id"),
|
||||
@NamedQuery(name="findAnyResourceIdByOwner", query="select distinct(r) from ResourceEntity r left join fetch r.scopes s where r.owner = :owner"),
|
||||
@NamedQuery(name="findAnyResourceIdByOwnerOrdered", query="select distinct(r) from ResourceEntity r left join fetch r.scopes s where r.owner = :owner order by r.id"),
|
||||
@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"),
|
||||
|
|
|
@ -130,7 +130,7 @@ public class JPAResourceStore implements ResourceStore {
|
|||
queryName = pagination ? "findAnyResourceIdByOwnerOrdered" : "findAnyResourceIdByOwner";
|
||||
}
|
||||
|
||||
TypedQuery<ResourceEntity> query = entityManager.createNamedQuery(queryName, ResourceEntity.class);
|
||||
TypedQuery<String> query = entityManager.createNamedQuery(queryName, String.class);
|
||||
|
||||
query.setFlushMode(FlushModeType.COMMIT);
|
||||
query.setParameter("owner", ownerId);
|
||||
|
@ -145,10 +145,10 @@ public class JPAResourceStore implements ResourceStore {
|
|||
}
|
||||
|
||||
ResourceStore resourceStore = provider.getStoreFactory().getResourceStore();
|
||||
List<ResourceEntity> result = query.getResultList();
|
||||
List<String> result = query.getResultList();
|
||||
|
||||
for (ResourceEntity entity : result) {
|
||||
Resource cached = resourceStore.findById(entity.getId(), resourceServerId);
|
||||
for (String entity : result) {
|
||||
Resource cached = resourceStore.findById(entity, resourceServerId);
|
||||
|
||||
if (cached != null) {
|
||||
consumer.accept(cached);
|
||||
|
|
|
@ -244,7 +244,7 @@ public class ResourceAdapter extends AbstractAuthorizationModel implements Resou
|
|||
|
||||
@Override
|
||||
public boolean isFetched(String association) {
|
||||
return em.getEntityManagerFactory().getPersistenceUnitUtil().isLoaded(this, association);
|
||||
return em.getEntityManagerFactory().getPersistenceUnitUtil().isLoaded(this.entity, association);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ 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;
|
||||
|
@ -94,6 +95,7 @@ import org.keycloak.services.util.DefaultClientSessionContext;
|
|||
public class AuthorizationTokenService {
|
||||
|
||||
public static final String CLAIM_TOKEN_FORMAT_ID_TOKEN = "http://openid.net/specs/openid-connect-core-1_0.html#IDToken";
|
||||
public static final String CLAIM_TOKEN_FORMAT_JWT = "urn:ietf:params:oauth:token-type:jwt";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AuthorizationTokenService.class);
|
||||
private static final String RESPONSE_MODE_DECISION = "decision";
|
||||
|
@ -103,12 +105,11 @@ public class AuthorizationTokenService {
|
|||
|
||||
static {
|
||||
SUPPORTED_CLAIM_TOKEN_FORMATS = new HashMap<>();
|
||||
SUPPORTED_CLAIM_TOKEN_FORMATS.put("urn:ietf:params:oauth:token-type:jwt", (request, authorization) -> {
|
||||
SUPPORTED_CLAIM_TOKEN_FORMATS.put(CLAIM_TOKEN_FORMAT_JWT, (request, authorization) -> {
|
||||
Map claims = request.getClaims();
|
||||
String claimToken = request.getClaimToken();
|
||||
|
||||
if (claimToken != null) {
|
||||
Map claims;
|
||||
|
||||
try {
|
||||
claims = JsonSerialization.readValue(Base64Url.decode(request.getClaimToken()), Map.class);
|
||||
request.setClaims(claims);
|
||||
|
@ -116,20 +117,18 @@ public class AuthorizationTokenService {
|
|||
throw new CorsErrorResponseException(request.getCors(), "invalid_request", "Invalid claims",
|
||||
Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
KeycloakIdentity identity;
|
||||
|
||||
try {
|
||||
identity = new KeycloakIdentity(authorization.getKeycloakSession(),
|
||||
Tokens.getAccessToken(request.getSubjectToken(), authorization.getKeycloakSession()));
|
||||
} catch (Exception cause) {
|
||||
throw new CorsErrorResponseException(request.getCors(), "unauthorized_client", "Invalid identity", Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
return new DefaultEvaluationContext(identity, claims, authorization.getKeycloakSession());
|
||||
}
|
||||
|
||||
throw new CorsErrorResponseException(request.getCors(), "invalid_request", "Claim token can not be null", Status.BAD_REQUEST);
|
||||
KeycloakIdentity identity;
|
||||
|
||||
try {
|
||||
identity = new KeycloakIdentity(authorization.getKeycloakSession(),
|
||||
Tokens.getAccessToken(request.getSubjectToken(), authorization.getKeycloakSession()));
|
||||
} catch (Exception cause) {
|
||||
throw new CorsErrorResponseException(request.getCors(), "unauthorized_client", "Invalid identity", Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
return new DefaultEvaluationContext(identity, claims, authorization.getKeycloakSession());
|
||||
});
|
||||
SUPPORTED_CLAIM_TOKEN_FORMATS.put(CLAIM_TOKEN_FORMAT_ID_TOKEN, (request, authorization) -> {
|
||||
KeycloakSession keycloakSession = authorization.getKeycloakSession();
|
||||
|
@ -397,7 +396,7 @@ public class AuthorizationTokenService {
|
|||
String claimTokenFormat = request.getClaimTokenFormat();
|
||||
|
||||
if (claimTokenFormat == null) {
|
||||
claimTokenFormat = CLAIM_TOKEN_FORMAT_ID_TOKEN;
|
||||
claimTokenFormat = CLAIM_TOKEN_FORMAT_JWT;
|
||||
}
|
||||
|
||||
BiFunction<KeycloakAuthorizationRequest, AuthorizationProvider, EvaluationContext> evaluationContextProvider = SUPPORTED_CLAIM_TOKEN_FORMATS.get(claimTokenFormat);
|
||||
|
|
|
@ -5,6 +5,7 @@ import javax.ws.rs.core.Response;
|
|||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.resource.AuthorizationResource;
|
||||
import org.keycloak.performance.dataset.idm.Client;
|
||||
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
||||
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
||||
import org.keycloak.performance.dataset.NestedEntity;
|
||||
import org.keycloak.performance.dataset.Updatable;
|
||||
|
@ -46,6 +47,7 @@ public class ResourceServer extends NestedEntity<Client, ResourceServerRepresent
|
|||
r.setId(getClient().getRepresentation().getId());
|
||||
r.setClientId(getClient().getRepresentation().getClientId());
|
||||
r.setName(getClient().getRepresentation().getName());
|
||||
r.setDecisionStrategy(DecisionStrategy.UNANIMOUS);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue