diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java index 1b0137a5d2..8429f73ad3 100644 --- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java +++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java @@ -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)"), diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ResourceEntity.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ResourceEntity.java index 1f2b88c51c..f8a7c0916b 100644 --- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ResourceEntity.java +++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ResourceEntity.java @@ -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"), diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java index 52d710ea2a..8d9234b7c7 100644 --- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java +++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java @@ -130,7 +130,7 @@ public class JPAResourceStore implements ResourceStore { queryName = pagination ? "findAnyResourceIdByOwnerOrdered" : "findAnyResourceIdByOwner"; } - TypedQuery query = entityManager.createNamedQuery(queryName, ResourceEntity.class); + TypedQuery 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 result = query.getResultList(); + List 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); diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/ResourceAdapter.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/ResourceAdapter.java index 44f72263d9..bc40f28df1 100644 --- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/ResourceAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/ResourceAdapter.java @@ -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); } diff --git a/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java b/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java index ac5b199ba9..f3e8e5cc71 100644 --- a/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java +++ b/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java @@ -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 evaluationContextProvider = SUPPORTED_CLAIM_TOKEN_FORMATS.get(claimTokenFormat); diff --git a/testsuite/performance/tests/src/main/java/org/keycloak/performance/dataset/idm/authorization/ResourceServer.java b/testsuite/performance/tests/src/main/java/org/keycloak/performance/dataset/idm/authorization/ResourceServer.java index 503bfc8580..84cc72cd42 100644 --- a/testsuite/performance/tests/src/main/java/org/keycloak/performance/dataset/idm/authorization/ResourceServer.java +++ b/testsuite/performance/tests/src/main/java/org/keycloak/performance/dataset/idm/authorization/ResourceServer.java @@ -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