From cd947ce3bca58ed89e4489cc651abf1ddd314006 Mon Sep 17 00:00:00 2001 From: mposolda Date: Fri, 16 Aug 2024 11:07:57 +0200 Subject: [PATCH] Removing policy-enforcer from Keycloak repository closes #32191 Signed-off-by: mposolda --- authz/policy-enforcer/pom.xml | 54 -- .../adapters/authorization/PathCache.java | 203 ----- .../authorization/PathConfigMatcher.java | 293 -------- .../authorization/PolicyEnforcer.java | 669 ----------------- .../authorization/TokenPrincipal.java | 56 -- .../cip/ClaimsInformationPointProvider.java | 74 -- ...ClaimsInformationPointProviderFactory.java | 37 - .../HttpClaimInformationPointProvider.java | 207 ----- ...pClaimInformationPointProviderFactory.java | 45 -- .../spi/ClaimInformationPointProvider.java | 30 - .../ClaimInformationPointProviderFactory.java | 35 - .../elytron/ElytronPolicyEnforcerFilter.java | 53 -- .../PolicyEnforcerServletContextListener.java | 81 -- .../elytron/ServletHttpRequest.java | 139 ---- .../elytron/ServletHttpResponse.java | 58 -- .../jakarta/ServletPolicyEnforcerFilter.java | 125 ---- .../spi/ConfigurationResolver.java | 36 - .../authorization/spi/HttpRequest.java | 114 --- .../authorization/spi/HttpResponse.java | 48 -- .../authorization/util/JsonUtils.java | 78 -- ...oakSecurityContextPlaceHolderResolver.java | 55 -- .../util/PlaceHolderResolver.java | 30 - .../authorization/util/PlaceHolders.java | 112 --- .../util/RequestPlaceHolderResolver.java | 170 ----- ...p.spi.ClaimInformationPointProviderFactory | 19 - authz/pom.xml | 1 - pom.xml | 5 - .../testsuite/util/AuthzTestUtils.java | 219 ------ .../authz/AuthzClientCredentialsTest.java | 18 +- .../ClaimInformationPointProviderTest.java | 317 -------- .../authz/admin/EnforcerConfigTest.java | 84 --- .../authz/admin/MyCustomCIPFactory.java | 57 -- .../authz/admin/PolicyEnforcerClaimsTest.java | 386 ---------- .../authz/admin/PolicyEnforcerTest.java | 706 ------------------ ...p.spi.ClaimInformationPointProviderFactory | 18 - .../enforcer-bearer-only-with-cip.json | 26 - .../enforcer-bearer-only.json | 8 - .../enforcer-config-claims-provider.json | 101 --- .../enforcer-config-path-cip.json | 28 - .../enforcer-config-paths-same-name.json | 54 -- .../enforcer-disabled-enforce-mode-path.json | 15 - .../enforcer-disabled-enforce-mode.json | 15 - .../enforcer-disabled-path-nocache.json | 27 - .../enforcer-entitlement-claims-test.json | 26 - .../enforcer-lazyload-with-paths.json | 15 - .../authorization-test/enforcer-lazyload.json | 9 - .../enforcer-match-http-verbs-scopes.json | 9 - .../enforcer-no-lazyload.json | 8 - .../enforcer-on-deny-redirect.json | 9 - .../enforcer-paths-use-method-config.json | 23 - .../authorization-test/enforcer-paths.json | 20 - .../enforcer-uma-claims-test.json | 27 - .../authorization-test/test-authz-realm.json | 48 -- testsuite/integration-arquillian/util/pom.xml | 4 - 54 files changed, 12 insertions(+), 5092 deletions(-) delete mode 100755 authz/policy-enforcer/pom.xml delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PathCache.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PathConfigMatcher.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/TokenPrincipal.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/ClaimsInformationPointProvider.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/ClaimsInformationPointProviderFactory.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/HttpClaimInformationPointProvider.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/HttpClaimInformationPointProviderFactory.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/spi/ClaimInformationPointProvider.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/spi/ClaimInformationPointProviderFactory.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ElytronPolicyEnforcerFilter.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/PolicyEnforcerServletContextListener.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ServletHttpRequest.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ServletHttpResponse.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/jakarta/ServletPolicyEnforcerFilter.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/ConfigurationResolver.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/HttpRequest.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/HttpResponse.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/JsonUtils.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/KeycloakSecurityContextPlaceHolderResolver.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/PlaceHolderResolver.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/PlaceHolders.java delete mode 100644 authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/RequestPlaceHolderResolver.java delete mode 100644 authz/policy-enforcer/src/main/resources/META-INF/services/org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory delete mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/AuthzTestUtils.java delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/ClaimInformationPointProviderTest.java delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/EnforcerConfigTest.java delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/MyCustomCIPFactory.java delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/PolicyEnforcerClaimsTest.java delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/PolicyEnforcerTest.java delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/services/org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-bearer-only-with-cip.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-bearer-only.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-claims-provider.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-path-cip.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-enforce-mode-path.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-enforce-mode.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-path-nocache.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-entitlement-claims-test.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-lazyload-with-paths.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-lazyload.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-match-http-verbs-scopes.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-no-lazyload.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-on-deny-redirect.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-paths-use-method-config.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-paths.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-uma-claims-test.json delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json diff --git a/authz/policy-enforcer/pom.xml b/authz/policy-enforcer/pom.xml deleted file mode 100755 index fae7b26126..0000000000 --- a/authz/policy-enforcer/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - org.keycloak - keycloak-authz-parent - 999.0.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - keycloak-policy-enforcer-tests - Keycloak Authz: Policy Enforcer for tests - Keycloak Policy Enforcer. This module is supposed to be used just in the Keycloak repository for the testsuite. It is NOT supposed to be used by the 3rd party applications. - For the use by 3rd party applications, please use `org.keycloak:keycloak-policy-enforcer` module. - jar - - - - org.keycloak - keycloak-authz-client-tests - - - - - jakarta.servlet - jakarta.servlet-api - true - - - org.wildfly.security - wildfly-elytron-http-oidc - true - - - - diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PathCache.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PathCache.java deleted file mode 100644 index 8aa66a9613..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PathCache.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.LockSupport; - -import org.keycloak.common.util.Time; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig; - -/** - * A simple LRU cache implementation supporting expiration and maximum number of entries. - * - * @author Pedro Igor - */ -public class PathCache { - - /** - * The load factor. - */ - private static final float DEFAULT_LOAD_FACTOR = 0.75f; - - private final Map cache; - - private final AtomicBoolean writing = new AtomicBoolean(false); - - private final long maxAge; - private final boolean enabled; - private final Map paths; - - /** - * Creates a new instance. - * @param maxEntries the maximum number of entries to keep in the cache - * @param maxAge the time in milliseconds that an entry can stay in the cache. If {@code -1}, entries never expire - * @param paths the pre-configured paths - */ - PathCache(final int maxEntries, long maxAge, - Map paths) { - cache = Collections.synchronizedMap(new LinkedHashMap(16, DEFAULT_LOAD_FACTOR, true) { - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - return cache.size() > maxEntries; - } - }); - this.maxAge = maxAge; - this.enabled = ! (maxAge < -1 || (maxAge > -1 && maxAge <= 0)); - this.paths = paths; - } - - public void put(String uri, PathConfig newValue) { - if (!enabled) { - if (newValue != null) { - // if disabled we also remove from the pre-defined paths map - markForInvalidation(newValue); - } - return; - } - - try { - if (parkForWriteAndCheckInterrupt()) { - return; - } - - CacheEntry cacheEntry = cache.get(uri); - - if (cacheEntry == null) { - cache.put(uri, new CacheEntry(uri, newValue, maxAge)); - } - } finally { - writing.lazySet(false); - } - } - - private void markForInvalidation(PathConfig newValue) { - PathConfig pathConfig = paths.get(newValue.getPath()); - - if (pathConfig != null && !pathConfig.isStatic()) { - // invalidate the configuration so that the path config is reload based on latest changes on the server - pathConfig.invalidate(); - } - } - - public boolean containsKey(String uri) { - return cache.containsKey(uri); - } - - public PathConfig get(String uri) { - if (parkForReadAndCheckInterrupt()) { - return null; - } - - CacheEntry cached = cache.get(uri); - - if (cached != null) { - return removeIfExpired(cached); - } - - return null; - } - - public void remove(String key) { - try { - if (parkForWriteAndCheckInterrupt()) { - return; - } - - cache.remove(key); - } finally { - writing.lazySet(false); - } - } - - private PathConfig removeIfExpired(CacheEntry cached) { - if (cached == null) { - return null; - } - - PathConfig config = cached.value(); - - if (cached.isExpired()) { - remove(cached.key()); - - if (config != null && config.getPath() != null) { - // also remove from pre-defined paths map so that changes on the server are properly reflected - markForInvalidation(config); - } - return null; - } - - return config; - } - - private boolean parkForWriteAndCheckInterrupt() { - while (!writing.compareAndSet(false, true)) { - LockSupport.parkNanos(1L); - if (Thread.interrupted()) { - return true; - } - } - return false; - } - - private boolean parkForReadAndCheckInterrupt() { - while (writing.get()) { - LockSupport.parkNanos(1L); - if (Thread.interrupted()) { - return true; - } - } - return false; - } - - public int size() { - return cache.size(); - } - - private static final class CacheEntry { - - final String key; - final PathConfig value; - final long expiration; - - CacheEntry(String key, PathConfig value, long maxAge) { - this.key = key; - this.value = value; - if(maxAge == -1) { - expiration = -1; - } else { - expiration = Time.currentTimeMillis() + maxAge; - } - } - - String key() { - return key; - } - - PathConfig value() { - return value; - } - - boolean isExpired() { - return expiration != -1 ? Time.currentTimeMillis() > expiration : false; - } - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PathConfigMatcher.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PathConfigMatcher.java deleted file mode 100644 index 2e1b75a3fc..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PathConfigMatcher.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.adapters.authorization; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.jboss.logging.Logger; -import org.keycloak.authorization.client.AuthzClient; -import org.keycloak.authorization.client.resource.ProtectedResource; -import org.keycloak.common.util.PathMatcher; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathCacheConfig; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig; -import org.keycloak.representations.idm.authorization.ResourceRepresentation; - -/** - * @author Pedro Igor - */ -public class PathConfigMatcher extends PathMatcher { - - private static Logger LOGGER = Logger.getLogger(PolicyEnforcer.class); - - private final Map paths; - private final PathCache pathCache; - private final AuthzClient authzClient; - private final PolicyEnforcerConfig enforcerConfig; - - PathConfigMatcher(PolicyEnforcerConfig enforcerConfig, AuthzClient authzClient) { - this.enforcerConfig = enforcerConfig; - PathCacheConfig cacheConfig = enforcerConfig.getPathCacheConfig(); - - if (cacheConfig == null) { - cacheConfig = new PathCacheConfig(); - } - - this.authzClient = authzClient; - this.paths = configurePaths(); - this.pathCache = new PathCache(cacheConfig.getMaxEntries(), cacheConfig.getLifespan(), paths); - - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Initialization complete. Path configuration:"); - for (PathConfig pathConfig : this.paths.values()) { - LOGGER.debug(pathConfig); - } - } - } - - @Override - public PathConfig matches(String targetUri) { - PathConfig pathConfig = pathCache.get(targetUri); - - if (pathCache.containsKey(targetUri) || pathConfig != null) { - return pathConfig; - } - - pathConfig = super.matches(targetUri); - - if (enforcerConfig.getLazyLoadPaths() || enforcerConfig.getPathCacheConfig() != null) { - if ((pathConfig == null || pathConfig.isInvalidated() || pathConfig.getPath().contains("*"))) { - try { - List matchingResources = authzClient.protection().resource().findByMatchingUri(targetUri); - - if (matchingResources.isEmpty()) { - // if this config is invalidated (e.g.: due to cache expiration) we remove and return null - if (pathConfig != null && pathConfig.isInvalidated()) { - paths.remove(targetUri); - return null; - } - } else { - Map> cipConfig = null; - PolicyEnforcerConfig.EnforcementMode enforcementMode = PolicyEnforcerConfig.EnforcementMode.ENFORCING; - ResourceRepresentation targetResource = matchingResources.get(0); - List methodConfig = null; - boolean isStatic = false; - - if (pathConfig != null) { - cipConfig = pathConfig.getClaimInformationPointConfig(); - enforcementMode = pathConfig.getEnforcementMode(); - methodConfig = pathConfig.getMethods(); - isStatic = pathConfig.isStatic(); - } else { - for (PathConfig existingPath : paths.values()) { - if (targetResource.getId().equals(existingPath.getId()) - && existingPath.isStatic() - && !org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode.DISABLED.equals(existingPath.getEnforcementMode())) { - return null; - } - } - } - - pathConfig = PathConfig.createPathConfigs(targetResource).iterator().next(); - - if (cipConfig != null) { - pathConfig.setClaimInformationPointConfig(cipConfig); - } - - if (methodConfig != null) { - pathConfig.setMethods(methodConfig); - } - - pathConfig.setStatic(isStatic); - pathConfig.setEnforcementMode(enforcementMode); - } - } catch (Exception cause) { - LOGGER.errorf(cause, "Could not lazy load resource with path [" + targetUri + "] from server"); - return null; - } - } - } - - pathCache.put(targetUri, pathConfig); - - return pathConfig; - } - - @Override - protected String getPath(PathConfig entry) { - return entry.getPath(); - } - - @Override - protected Collection getPaths() { - return paths.values(); - } - - public PathCache getPathCache() { - return pathCache; - } - - @Override - protected PathConfig resolvePathConfig(PathConfig originalConfig, String path) { - if (originalConfig.hasPattern()) { - ProtectedResource resource = authzClient.protection().resource(); - - // search by an exact match - List search = resource.findByUri(path); - - // if exact match not found, try to obtain from current path the parent path. - // if path is /resource/1/test and pattern from pathConfig is /resource/{id}/*, parent path is /resource/1 - // this logic allows to match sub resources of a resource instance (/resource/1) to the parent resource, - // so any permission granted to parent also applies to sub resources - if (search.isEmpty()) { - search = resource.findByUri(buildUriFromTemplate(originalConfig.getPath(), path, true)); - } - - if (!search.isEmpty()) { - ResourceRepresentation targetResource = search.get(0); - PathConfig config = PathConfig.createPathConfigs(targetResource).iterator().next(); - - config.setScopes(originalConfig.getScopes()); - config.setMethods(originalConfig.getMethods()); - config.setParentConfig(originalConfig); - config.setEnforcementMode(originalConfig.getEnforcementMode()); - config.setClaimInformationPointConfig(originalConfig.getClaimInformationPointConfig()); - - return config; - } - } - - return null; - } - - public void removeFromCache(String pathConfig) { - pathCache.remove(pathConfig); - } - - public Map getPathConfig() { - return paths; - } - - private Map configurePaths() { - ProtectedResource protectedResource = this.authzClient.protection().resource(); - boolean loadPathsFromServer = !enforcerConfig.getLazyLoadPaths(); - - for (PathConfig pathConfig : enforcerConfig.getPaths()) { - if (!org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode.DISABLED.equals(pathConfig.getEnforcementMode())) { - loadPathsFromServer = false; - break; - } - } - - if (loadPathsFromServer) { - LOGGER.info("No path provided in configuration."); - Map paths = configureAllPathsForResourceServer(protectedResource); - - paths.putAll(configureDefinedPaths(protectedResource, enforcerConfig)); - - return paths; - } else { - LOGGER.info("Paths provided in configuration."); - return configureDefinedPaths(protectedResource, enforcerConfig); - } - } - - private Map configureDefinedPaths(ProtectedResource protectedResource, PolicyEnforcerConfig enforcerConfig) { - Map paths = Collections.synchronizedMap(new LinkedHashMap()); - - for (PathConfig pathConfig : enforcerConfig.getPaths()) { - ResourceRepresentation resource; - String resourceName = pathConfig.getName(); - String path = pathConfig.getPath(); - - if (resourceName != null) { - LOGGER.debugf("Trying to find resource with name [%s] for path [%s].", resourceName, path); - resource = protectedResource.findByName(resourceName); - } else { - LOGGER.debugf("Trying to find resource with uri [%s] for path [%s].", path, path); - List resources = protectedResource.findByUri(path); - - if (resources.isEmpty()) { - resources = protectedResource.findByMatchingUri(path); - } - - if (resources.size() == 1) { - resource = resources.get(0); - } else if (resources.size() > 1) { - throw new RuntimeException("Multiple resources found with the same uri"); - } else { - resource = null; - } - } - - if (resource != null) { - pathConfig.setId(resource.getId()); - // if the resource is statically bound to a resource it means the config can not be invalidated - if (resourceName != null) { - pathConfig.setStatic(true); - } - } - - if (org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode.DISABLED.equals(pathConfig.getEnforcementMode())) { - pathConfig.setStatic(true); - } - - PathConfig existingPath = null; - - for (PathConfig current : paths.values()) { - if (current.getPath().equals(pathConfig.getPath())) { - existingPath = current; - break; - } - } - - if (existingPath == null) { - paths.put(pathConfig.getPath(), pathConfig); - } else { - existingPath.getMethods().addAll(pathConfig.getMethods()); - existingPath.getScopes().addAll(pathConfig.getScopes()); - } - } - - return paths; - } - - private Map configureAllPathsForResourceServer(ProtectedResource protectedResource) { - LOGGER.info("Querying the server for all resources associated with this application."); - Map paths = Collections.synchronizedMap(new HashMap()); - - if (!enforcerConfig.getLazyLoadPaths()) { - for (String id : protectedResource.findAll()) { - ResourceRepresentation resourceDescription = protectedResource.findById(id); - - if (resourceDescription.getUris() != null && !resourceDescription.getUris().isEmpty()) { - for(PathConfig pathConfig : PathConfig.createPathConfigs(resourceDescription)) { - paths.put(pathConfig.getPath(), pathConfig); - } - } - } - } - - return paths; - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java deleted file mode 100644 index 6c5bc73f89..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java +++ /dev/null @@ -1,669 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.keycloak.adapters.authorization; - -import static org.keycloak.adapters.authorization.util.JsonUtils.asAccessToken; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.ServiceLoader; -import java.util.Set; - -import org.apache.http.client.HttpClient; -import org.jboss.logging.Logger; -import org.keycloak.AuthorizationContext; -import org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory; -import org.keycloak.adapters.authorization.spi.HttpRequest; -import org.keycloak.adapters.authorization.spi.HttpResponse; -import org.keycloak.authorization.client.AuthorizationDeniedException; -import org.keycloak.authorization.client.AuthzClient; -import org.keycloak.authorization.client.ClientAuthorizationContext; -import org.keycloak.authorization.client.Configuration; -import org.keycloak.authorization.client.resource.PermissionResource; -import org.keycloak.authorization.client.resource.ProtectionResource; -import org.keycloak.common.util.Base64; -import org.keycloak.protocol.oidc.client.authentication.ClientCredentialsProvider; -import org.keycloak.representations.AccessToken; -import org.keycloak.representations.AccessToken.Authorization; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.MethodConfig; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.ScopeEnforcementMode; -import org.keycloak.representations.idm.authorization.AuthorizationRequest; -import org.keycloak.representations.idm.authorization.AuthorizationResponse; -import org.keycloak.representations.idm.authorization.Permission; -import org.keycloak.representations.idm.authorization.PermissionRequest; -import org.keycloak.util.JsonSerialization; - -/** - *

A Policy Enforcement Point (PEP) that requests and enforces authorization decisions from Keycloak. - * - * @author Pedro Igor - */ -public class PolicyEnforcer { - - private static Logger LOGGER = Logger.getLogger(PolicyEnforcer.class); - private static final String HTTP_METHOD_DELETE = "DELETE"; - - public static Builder builder() { - return new Builder(); - } - - private final AuthzClient authzClient; - private final Map paths; - private final PathConfigMatcher pathMatcher; - private final HttpClient httpClient; - private final PolicyEnforcerConfig enforcerConfig; - - private final Map claimInformationPointProviderFactories = new HashMap<>(); - - protected PolicyEnforcer(Builder builder) { - enforcerConfig = builder.getEnforcerConfig(); - Configuration authzClientConfig = builder.authzClientConfig; - - if (authzClientConfig.getRealm() == null) { - authzClientConfig.setRealm(enforcerConfig.getRealm()); - } - - if (authzClientConfig.getAuthServerUrl() == null) { - authzClientConfig.setAuthServerUrl(enforcerConfig.getAuthServerUrl()); - } - - if (authzClientConfig.getCredentials() == null || authzClientConfig.getCredentials().isEmpty()) { - authzClientConfig.setCredentials(enforcerConfig.getCredentials()); - } - - if (authzClientConfig.getResource() == null) { - authzClientConfig.setResource(enforcerConfig.getResource()); - } - - authzClient = AuthzClient.create(authzClientConfig); - httpClient = authzClient.getConfiguration().getHttpClient(); - pathMatcher = new PathConfigMatcher(builder.getEnforcerConfig(), authzClient); - paths = pathMatcher.getPathConfig(); - - loadClaimInformationPointProviders(ServiceLoader.load(ClaimInformationPointProviderFactory.class, ClaimInformationPointProviderFactory.class.getClassLoader())); - loadClaimInformationPointProviders(ServiceLoader.load(ClaimInformationPointProviderFactory.class, Thread.currentThread().getContextClassLoader())); - } - - public AuthorizationContext enforce(HttpRequest request, HttpResponse response) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debugv("Policy enforcement is enabled. Enforcing policy decisions for path [{0}].", request.getURI()); - } - - AuthorizationContext context = authorize(request, response); - - if (LOGGER.isDebugEnabled()) { - LOGGER.debugv("Policy enforcement result for path [{0}] is : {1}", request.getURI(), context.isGranted() ? "GRANTED" : "DENIED"); - LOGGER.debugv("Returning authorization context with permissions:"); - for (Permission permission : context.getPermissions()) { - LOGGER.debug(permission); - } - } - - return context; - } - - public HttpClient getHttpClient() { - return httpClient; - } - - public AuthzClient getAuthzClient() { - return authzClient; - } - - public Map getPaths() { - return Collections.unmodifiableMap(paths); - } - - public Map getClaimInformationPointProviderFactories() { - return claimInformationPointProviderFactories; - } - - public PathConfigMatcher getPathMatcher() { - return pathMatcher; - } - - private AuthorizationContext authorize(HttpRequest request, HttpResponse response) { - EnforcementMode enforcementMode = enforcerConfig.getEnforcementMode(); - TokenPrincipal principal = request.getPrincipal(); - boolean anonymous = principal == null || principal.getRawToken() == null; - - if (EnforcementMode.DISABLED.equals(enforcementMode)) { - if (anonymous) { - response.sendError(401, "Invalid bearer"); - } - return createEmptyAuthorizationContext(true); - } - - PathConfig pathConfig = getPathConfig(request); - - if (anonymous) { - if (!isDefaultAccessDeniedUri(request)) { - if (pathConfig != null) { - if (EnforcementMode.DISABLED.equals(pathConfig.getEnforcementMode())) { - return createEmptyAuthorizationContext(true); - } else { - challenge(pathConfig, getRequiredScopes(pathConfig, request), request, response); - } - } else { - handleAccessDenied(response); - } - } - return createEmptyAuthorizationContext(false); - } - - AccessToken accessToken = principal.getToken(); - - if (accessToken != null) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debugf("Checking permissions for path [%s] with config [%s].", request.getURI(), pathConfig); - } - - if (pathConfig == null) { - if (EnforcementMode.PERMISSIVE.equals(enforcementMode)) { - return createAuthorizationContext(accessToken, null); - } - - if (LOGGER.isDebugEnabled()) { - LOGGER.debugf("Could not find a configuration for path [%s]", getPath(request)); - } - - if (isDefaultAccessDeniedUri(request)) { - return createAuthorizationContext(accessToken, null); - } - - handleAccessDenied(response); - - return createEmptyAuthorizationContext(false); - } - - if (EnforcementMode.DISABLED.equals(pathConfig.getEnforcementMode())) { - return createAuthorizationContext(accessToken, pathConfig); - } - - MethodConfig methodConfig = getRequiredScopes(pathConfig, request); - Map> claims = resolveClaims(pathConfig, request); - - if (isAuthorized(pathConfig, methodConfig, accessToken, request, claims)) { - try { - return createAuthorizationContext(accessToken, pathConfig); - } catch (Exception e) { - throw new RuntimeException("Error processing path [" + pathConfig.getPath() + "].", e); - } - } - - AccessToken original = accessToken; - - accessToken = requestAuthorizationToken(pathConfig, methodConfig, request, claims); - - if (accessToken != null) { - AccessToken.Authorization authorization = original.getAuthorization(); - - if (authorization == null) { - authorization = new AccessToken.Authorization(); - authorization.setPermissions(new ArrayList()); - } - - AccessToken.Authorization newAuthorization = accessToken.getAuthorization(); - - if (newAuthorization != null) { - Collection grantedPermissions = authorization.getPermissions(); - Collection newPermissions = newAuthorization.getPermissions(); - - for (Permission newPermission : newPermissions) { - if (!grantedPermissions.contains(newPermission)) { - grantedPermissions.add(newPermission); - } - } - } - - original.setAuthorization(authorization); - - if (isAuthorized(pathConfig, methodConfig, accessToken, request, claims)) { - try { - return createAuthorizationContext(accessToken, pathConfig); - } catch (Exception e) { - throw new RuntimeException("Error processing path [" + pathConfig.getPath() + "].", e); - } - } - } - - if (methodConfig != null && ScopeEnforcementMode.DISABLED.equals(methodConfig.getScopesEnforcementMode())) { - return createEmptyAuthorizationContext(true); - } - - if (LOGGER.isDebugEnabled()) { - LOGGER.debugf("Sending challenge to the client. Path [%s]", pathConfig); - } - - if (!challenge(pathConfig, methodConfig, request, response)) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debugf("Challenge not sent, sending default forbidden response. Path [%s]", pathConfig); - } - handleAccessDenied(response); - } - } - - return createEmptyAuthorizationContext(false); - } - - protected boolean isAuthorized(PathConfig actualPathConfig, MethodConfig methodConfig, AccessToken accessToken, HttpRequest request, Map> claims) { - if (isDefaultAccessDeniedUri(request)) { - return true; - } - - Authorization authorization = accessToken.getAuthorization(); - - if (authorization == null) { - return false; - } - - boolean hasPermission = false; - Collection grantedPermissions = authorization.getPermissions(); - - for (Permission permission : grantedPermissions) { - if (permission.getResourceId() != null) { - if (isResourcePermission(actualPathConfig, permission)) { - hasPermission = true; - - if (actualPathConfig.isInstance() && !matchResourcePermission(actualPathConfig, permission)) { - continue; - } - - if (hasResourceScopePermission(methodConfig, permission)) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debugf("Authorization GRANTED for path [%s]. Permissions [%s].", actualPathConfig, grantedPermissions); - } - if (HTTP_METHOD_DELETE.equalsIgnoreCase(request.getMethod()) && actualPathConfig.isInstance()) { - pathMatcher.removeFromCache(getPath(request)); - } - - return hasValidClaims(permission, claims); - } - } - } else { - if (hasResourceScopePermission(methodConfig, permission)) { - return true; - } - } - } - - if (!hasPermission && EnforcementMode.PERMISSIVE.equals(actualPathConfig.getEnforcementMode())) { - return true; - } - - if (LOGGER.isDebugEnabled()) { - LOGGER.debugf("Authorization FAILED for path [%s]. Not enough permissions [%s].", actualPathConfig, grantedPermissions); - } - - return false; - } - - protected Map> resolveClaims(PathConfig pathConfig, HttpRequest request) { - Map> claims = new HashMap<>(); - - resolveClaims(claims, enforcerConfig.getClaimInformationPointConfig(), request); - resolveClaims(claims, pathConfig.getClaimInformationPointConfig(), request); - - return claims; - } - - protected boolean challenge(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, HttpRequest request, HttpResponse response) { - if (isBearerAuthorization(request)) { - String ticket = getPermissionTicket(pathConfig, methodConfig, authzClient, request); - - if (ticket != null) { - response.setHeader("WWW-Authenticate", new StringBuilder("UMA realm=\"").append(authzClient.getConfiguration().getRealm()).append("\"").append(",as_uri=\"") - .append(authzClient.getServerConfiguration().getIssuer()).append("\"").append(",ticket=\"").append(ticket).append("\"").toString()); - response.sendError(401); - } else { - response.sendError(403); - } - - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Sending challenge"); - } - - return true; - } - - handleAccessDenied(response); - - return true; - } - - protected void handleAccessDenied(HttpResponse response) { - String accessDeniedPath = enforcerConfig.getOnDenyRedirectTo(); - - if (accessDeniedPath != null) { - response.setHeader("Location", accessDeniedPath); - response.sendError(302); - } else { - response.sendError(403); - } - } - - private boolean hasValidClaims(Permission permission, Map> claims) { - Map> grantedClaims = permission.getClaims(); - - if (grantedClaims != null) { - if (claims.isEmpty()) { - return false; - } - - for (Entry> entry : grantedClaims.entrySet()) { - List requestClaims = claims.get(entry.getKey()); - - if (requestClaims == null || requestClaims.isEmpty() || !entry.getValue().containsAll(requestClaims)) { - return false; - } - } - } - - return true; - } - - private boolean isDefaultAccessDeniedUri(HttpRequest request) { - String accessDeniedPath = enforcerConfig.getOnDenyRedirectTo(); - return accessDeniedPath != null && request.getURI().contains(accessDeniedPath); - } - - private boolean hasResourceScopePermission(MethodConfig methodConfig, Permission permission) { - List requiredScopes = methodConfig.getScopes(); - Set allowedScopes = permission.getScopes(); - - if (allowedScopes.isEmpty()) { - return true; - } - - PolicyEnforcerConfig.ScopeEnforcementMode enforcementMode = methodConfig.getScopesEnforcementMode(); - - if (PolicyEnforcerConfig.ScopeEnforcementMode.ALL.equals(enforcementMode)) { - return allowedScopes.containsAll(requiredScopes); - } - - if (PolicyEnforcerConfig.ScopeEnforcementMode.ANY.equals(enforcementMode)) { - for (String requiredScope : requiredScopes) { - if (allowedScopes.contains(requiredScope)) { - return true; - } - } - } - - return requiredScopes.isEmpty(); - } - - private AuthorizationContext createEmptyAuthorizationContext(final boolean granted) { - return new ClientAuthorizationContext(authzClient) { - @Override - public boolean hasPermission(String resourceName, String scopeName) { - return granted; - } - - @Override - public boolean hasResourcePermission(String resourceName) { - return granted; - } - - @Override - public boolean hasScopePermission(String scopeName) { - return granted; - } - - @Override - public List getPermissions() { - return Collections.EMPTY_LIST; - } - - @Override - public boolean isGranted() { - return granted; - } - }; - } - - private String getPath(HttpRequest request) { - return request.getRelativePath(); - } - - private MethodConfig getRequiredScopes(PathConfig pathConfig, HttpRequest request) { - String method = request.getMethod(); - - for (MethodConfig methodConfig : pathConfig.getMethods()) { - if (methodConfig.getMethod().equals(method)) { - return methodConfig; - } - } - - MethodConfig methodConfig = new MethodConfig(); - - methodConfig.setMethod(request.getMethod()); - List scopes = new ArrayList<>(); - - if (Boolean.TRUE.equals(enforcerConfig.getHttpMethodAsScope())) { - scopes.add(request.getMethod()); - } else { - scopes.addAll(pathConfig.getScopes()); - } - - methodConfig.setScopes(scopes); - methodConfig.setScopesEnforcementMode(PolicyEnforcerConfig.ScopeEnforcementMode.ANY); - - return methodConfig; - } - - private AuthorizationContext createAuthorizationContext(AccessToken accessToken, PathConfig pathConfig) { - return new ClientAuthorizationContext(accessToken, pathConfig, authzClient); - } - - private boolean isResourcePermission(PathConfig actualPathConfig, Permission permission) { - // first we try a match using resource id - boolean resourceMatch = matchResourcePermission(actualPathConfig, permission); - - // as a fallback, check if the current path is an instance and if so, check if parent's id matches the permission - if (!resourceMatch && actualPathConfig.isInstance()) { - resourceMatch = matchResourcePermission(actualPathConfig.getParentConfig(), permission); - } - - return resourceMatch; - } - - private boolean matchResourcePermission(PathConfig actualPathConfig, Permission permission) { - return permission.getResourceId().equals(actualPathConfig.getId()); - } - - private PathConfig getPathConfig(HttpRequest request) { - return isDefaultAccessDeniedUri(request) ? null : pathMatcher.matches(getPath(request)); - } - - private AccessToken requestAuthorizationToken(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, HttpRequest request, Map> claims) { - if (enforcerConfig.getUserManagedAccess() != null) { - return null; - } - - try { - TokenPrincipal principal = request.getPrincipal(); - String accessTokenString = principal.getRawToken(); - AccessToken accessToken = principal.getToken(); - AuthorizationRequest authzRequest = new AuthorizationRequest(); - - if (isBearerAuthorization(request) || accessToken.getAuthorization() != null) { - authzRequest.addPermission(pathConfig.getId(), methodConfig.getScopes()); - } - - if (!claims.isEmpty()) { - authzRequest.setClaimTokenFormat("urn:ietf:params:oauth:token-type:jwt"); - authzRequest.setClaimToken(Base64.encodeBytes(JsonSerialization.writeValueAsBytes(claims))); - } - - if (accessToken.getAuthorization() != null) { - authzRequest.setRpt(accessTokenString); - } - - LOGGER.debug("Obtaining authorization for authenticated user."); - AuthorizationResponse authzResponse; - - if (isBearerAuthorization(request)) { - authzRequest.setSubjectToken(accessTokenString); - authzResponse = authzClient.authorization().authorize(authzRequest); - } else { - authzResponse = authzClient.authorization(accessTokenString).authorize(authzRequest); - } - - if (authzResponse != null) { - return asAccessToken(authzResponse.getToken()); - } - } catch (AuthorizationDeniedException ignore) { - LOGGER.debug("Authorization denied", ignore); - } catch (Exception e) { - LOGGER.debug("Authorization failed", e); - } - - return null; - } - - private String getPermissionTicket(PathConfig pathConfig, MethodConfig methodConfig, AuthzClient authzClient, HttpRequest httpFacade) { - if (enforcerConfig.getUserManagedAccess() != null) { - ProtectionResource protection = authzClient.protection(); - PermissionResource permission = protection.permission(); - PermissionRequest permissionRequest = new PermissionRequest(); - - permissionRequest.setResourceId(pathConfig.getId()); - permissionRequest.setScopes(new HashSet<>(methodConfig.getScopes())); - - Map> claims = resolveClaims(pathConfig, httpFacade); - - if (!claims.isEmpty()) { - permissionRequest.setClaims(claims); - } - - return permission.create(permissionRequest).getTicket(); - } - - return null; - } - - private boolean isBearerAuthorization(HttpRequest request) { - List authHeaders = request.getHeaders("Authorization"); - - if (authHeaders != null) { - for (String authHeader : authHeaders) { - String[] split = authHeader.trim().split("\\s+"); - if (split == null || split.length != 2) continue; - if (!split[0].equalsIgnoreCase("Bearer")) continue; - return true; - } - } - - return authzClient.getConfiguration().isBearerOnly(); - } - - private void loadClaimInformationPointProviders(ServiceLoader loader) { - for (ClaimInformationPointProviderFactory factory : loader) { - factory.init(this); - - claimInformationPointProviderFactories.put(factory.getName(), factory); - } - } - - private void resolveClaims(Map> claims, Map> claimInformationPointConfig, HttpRequest request) { - if (claimInformationPointConfig != null) { - for (Entry> claimDef : claimInformationPointConfig.entrySet()) { - ClaimInformationPointProviderFactory factory = claimInformationPointProviderFactories.get(claimDef.getKey()); - - if (factory != null) { - claims.putAll(factory.create(claimDef.getValue()).resolve(request)); - } - } - } - } - - public static class Builder { - - Configuration authzClientConfig = new Configuration(); - - private Builder() { - } - - public Builder authServerUrl(String authServerUrl) { - authzClientConfig.setAuthServerUrl(authServerUrl); - return this; - } - - public Builder realm(String realm) { - authzClientConfig.setRealm(realm); - return this; - } - - public Builder clientId(String clientId) { - authzClientConfig.setResource(clientId); - return this; - } - - public Builder bearerOnly(boolean bearerOnly) { - authzClientConfig.setBearerOnly(bearerOnly); - return this; - } - - public Builder credentials(Map credentials) { - authzClientConfig.setCredentials(credentials); - return this; - } - - public Builder enforcerConfig(PolicyEnforcerConfig enforcerConfig) { - authzClientConfig.setPolicyEnforcerConfig(enforcerConfig); - return this; - } - - public Builder enforcerConfig(InputStream is) { - try { - enforcerConfig(JsonSerialization.readValue(is, PolicyEnforcerConfig.class)); - } catch (Exception cause) { - throw new RuntimeException("Failed to read configuration", cause); - } - return this; - } - - public Builder httpClient(HttpClient httpClient) { - authzClientConfig.setHttpClient(httpClient); - return this; - } - - public Builder credentialProvider(ClientCredentialsProvider credentialsProvider) { - authzClientConfig.setClientCredentialsProvider(credentialsProvider); - return this; - } - - public PolicyEnforcer build() { - return new PolicyEnforcer(this); - } - - PolicyEnforcerConfig getEnforcerConfig() { - return authzClientConfig.getPolicyEnforcerConfig(); - } - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/TokenPrincipal.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/TokenPrincipal.java deleted file mode 100644 index d47434382b..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/TokenPrincipal.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.adapters.authorization; - -import java.security.Principal; - -import org.keycloak.adapters.authorization.util.JsonUtils; -import org.keycloak.representations.AccessToken; - -/** - * A {@link Principal} backed by a token representing the entity requesting permissions. - * - * @author Pedro Igor - */ -public interface TokenPrincipal extends Principal { - - /** - * The token in its raw format. - * - * @return the token in its raw format. - */ - String getRawToken(); - - /** - * The {@link AccessToken} representation of {@link TokenPrincipal#getRawToken()}. - * - * @return the access token representation - */ - default AccessToken getToken() { - return JsonUtils.asAccessToken(getRawToken()); - } - - /** - * The name of the entity represented by the token. - * - * @return the name of the principal - */ - default String getName() { - return getToken().getPreferredUsername(); - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/ClaimsInformationPointProvider.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/ClaimsInformationPointProvider.java deleted file mode 100644 index 00eab06223..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/ClaimsInformationPointProvider.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.cip; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProvider; -import org.keycloak.adapters.authorization.spi.HttpRequest; -import org.keycloak.adapters.authorization.util.PlaceHolders; - -/** - * @author Pedro Igor - */ -public class ClaimsInformationPointProvider implements ClaimInformationPointProvider { - - private final Map config; - - public ClaimsInformationPointProvider(Map config) { - this.config = config; - } - - @Override - public Map> resolve(HttpRequest request) { - Map> claims = new HashMap<>(); - - for (Entry configEntry : config.entrySet()) { - String claimName = configEntry.getKey(); - Object claimValue = configEntry.getValue(); - List values = new ArrayList<>(); - - if (claimValue instanceof String) { - values = getValues(claimValue.toString(), request); - } else if (claimValue instanceof Collection) { - - for (Object value : Collection.class.cast(claimValue)) { - List resolvedValues = getValues(value.toString(), request); - - if (!resolvedValues.isEmpty()) { - values.addAll(resolvedValues); - } - } - } - - if (!values.isEmpty()) { - claims.put(claimName, values); - } - } - - return claims; - } - - private List getValues(String value, HttpRequest httpFacade) { - return PlaceHolders.resolve(value, httpFacade); - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/ClaimsInformationPointProviderFactory.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/ClaimsInformationPointProviderFactory.java deleted file mode 100644 index 7c1d82f0c6..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/ClaimsInformationPointProviderFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.cip; - -import java.util.Map; - -import org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory; - -/** - * @author Pedro Igor - */ -public class ClaimsInformationPointProviderFactory implements ClaimInformationPointProviderFactory { - - @Override - public String getName() { - return "claims"; - } - - @Override - public ClaimsInformationPointProvider create(Map config) { - return new ClaimsInformationPointProvider(config); - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/HttpClaimInformationPointProvider.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/HttpClaimInformationPointProvider.java deleted file mode 100644 index 958df54779..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/HttpClaimInformationPointProvider.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.cip; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import com.fasterxml.jackson.databind.JsonNode; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.RequestBuilder; -import org.apache.http.util.EntityUtils; -import org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProvider; -import org.keycloak.adapters.authorization.spi.HttpRequest; -import org.keycloak.adapters.authorization.util.JsonUtils; -import org.keycloak.adapters.authorization.util.PlaceHolders; -import org.keycloak.authorization.client.util.HttpResponseException; -import org.keycloak.common.util.StreamUtil; -import org.keycloak.util.JsonSerialization; - -/** - * @author Pedro Igor - */ -public class HttpClaimInformationPointProvider implements ClaimInformationPointProvider { - - private final Map config; - private final HttpClient httpClient; - - public HttpClaimInformationPointProvider(Map config, HttpClient httpClient) { - this.config = config; - this.httpClient = httpClient; - } - - @Override - public Map> resolve(HttpRequest request) { - try { - InputStream responseStream = executeRequest(request); - - try (InputStream inputStream = new BufferedInputStream(responseStream)) { - JsonNode jsonNode = JsonSerialization.mapper.readTree(inputStream); - Map> claims = new HashMap<>(); - Map claimsDef = (Map) config.get("claims"); - - if (claimsDef == null) { - Iterator nodeNames = jsonNode.fieldNames(); - - while (nodeNames.hasNext()) { - String nodeName = nodeNames.next(); - claims.put(nodeName, JsonUtils.getValues(jsonNode.get(nodeName))); - } - } else { - for (Entry claimDef : claimsDef.entrySet()) { - List jsonPaths = new ArrayList<>(); - - if (claimDef.getValue() instanceof Collection) { - jsonPaths.addAll(Collection.class.cast(claimDef.getValue())); - } else { - jsonPaths.add(claimDef.getValue().toString()); - } - - List claimValues = new ArrayList<>(); - - for (String path : jsonPaths) { - claimValues.addAll(JsonUtils.getValues(jsonNode, path)); - } - - claims.put(claimDef.getKey(), claimValues); - } - } - - return claims; - } - } catch (IOException cause) { - throw new RuntimeException("Could not obtain claims from http claim information point [" + config.get("url") + "] response", cause); - } - } - - private InputStream executeRequest(HttpRequest request) { - String method = config.get("method").toString(); - - if (method == null) { - method = "GET"; - } - - RequestBuilder builder = null; - - if ("GET".equalsIgnoreCase(method)) { - builder = RequestBuilder.get(); - } else { - builder = RequestBuilder.post(); - } - - builder.setUri(config.get("url").toString()); - - byte[] bytes = new byte[0]; - - try { - setParameters(builder, request); - - if (config.containsKey("headers")) { - setHeaders(builder, request); - } - - HttpResponse response = httpClient.execute(builder.build()); - HttpEntity entity = response.getEntity(); - - if (entity != null) { - bytes = EntityUtils.toByteArray(entity); - } - - StatusLine statusLine = response.getStatusLine(); - int statusCode = statusLine.getStatusCode(); - - if (statusCode < 200 || statusCode >= 300) { - throw new HttpResponseException("Unexpected response from server: " + statusCode + " / " + statusLine.getReasonPhrase(), statusCode, statusLine.getReasonPhrase(), bytes); - } - - return new ByteArrayInputStream(bytes); - } catch (Exception cause) { - try { - throw new RuntimeException("Error executing http method [" + builder + "]. Response : " + StreamUtil.readString(new ByteArrayInputStream(bytes), Charset.forName("UTF-8")), cause); - } catch (Exception e) { - throw new RuntimeException("Error executing http method [" + builder + "]", cause); - } - } - } - - private void setHeaders(RequestBuilder builder, HttpRequest request) { - Object headersDef = config.get("headers"); - - if (headersDef != null) { - Map headers = Map.class.cast(headersDef); - - for (Entry header : headers.entrySet()) { - Object value = header.getValue(); - List headerValues = new ArrayList<>(); - - if (value instanceof Collection) { - Collection values = Collection.class.cast(value); - - for (Object item : values) { - headerValues.addAll(PlaceHolders.resolve(item.toString(), request)); - } - } else { - headerValues.addAll(PlaceHolders.resolve(value.toString(), request)); - } - - for (String headerValue : headerValues) { - builder.addHeader(header.getKey(), headerValue); - } - } - } - } - - private void setParameters(RequestBuilder builder, HttpRequest request) { - Object config = this.config.get("parameters"); - - if (config != null) { - Map paramsDef = Map.class.cast(config); - - for (Entry paramDef : paramsDef.entrySet()) { - Object value = paramDef.getValue(); - List paramValues = new ArrayList<>(); - - if (value instanceof Collection) { - Collection values = Collection.class.cast(value); - - for (Object item : values) { - paramValues.addAll(PlaceHolders.resolve(item.toString(), request)); - } - } else { - paramValues.addAll(PlaceHolders.resolve(value.toString(), request)); - } - - for (String paramValue : paramValues) { - builder.addParameter(paramDef.getKey(), paramValue); - } - } - } - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/HttpClaimInformationPointProviderFactory.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/HttpClaimInformationPointProviderFactory.java deleted file mode 100644 index 3c9a4ec264..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/HttpClaimInformationPointProviderFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.cip; - -import java.util.Map; - -import org.keycloak.adapters.authorization.PolicyEnforcer; -import org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory; - -/** - * @author Pedro Igor - */ -public class HttpClaimInformationPointProviderFactory implements ClaimInformationPointProviderFactory { - - private PolicyEnforcer policyEnforcer; - - @Override - public String getName() { - return "http"; - } - - @Override - public void init(PolicyEnforcer policyEnforcer) { - this.policyEnforcer = policyEnforcer; - } - - @Override - public HttpClaimInformationPointProvider create(Map config) { - return new HttpClaimInformationPointProvider(config, policyEnforcer.getHttpClient()); - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/spi/ClaimInformationPointProvider.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/spi/ClaimInformationPointProvider.java deleted file mode 100644 index 43325a8c83..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/spi/ClaimInformationPointProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.cip.spi; - -import java.util.List; -import java.util.Map; - -import org.keycloak.adapters.authorization.spi.HttpRequest; - -/** - * @author Pedro Igor - */ -public interface ClaimInformationPointProvider { - - Map> resolve(HttpRequest request); -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/spi/ClaimInformationPointProviderFactory.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/spi/ClaimInformationPointProviderFactory.java deleted file mode 100644 index f9e1e305a7..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/cip/spi/ClaimInformationPointProviderFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.cip.spi; - -import java.util.Map; - -import org.keycloak.adapters.authorization.PolicyEnforcer; - -/** - * @author Pedro Igor - */ -public interface ClaimInformationPointProviderFactory { - - String getName(); - - default void init(PolicyEnforcer policyEnforcer) { - - } - - C create(Map config); -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ElytronPolicyEnforcerFilter.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ElytronPolicyEnforcerFilter.java deleted file mode 100644 index 99c42912e4..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ElytronPolicyEnforcerFilter.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.keycloak.adapters.authorization.integration.elytron; - -import java.security.Principal; - -import jakarta.servlet.http.HttpServletRequest; -import org.keycloak.adapters.authorization.PolicyEnforcer; -import org.keycloak.adapters.authorization.integration.jakarta.ServletPolicyEnforcerFilter; -import org.keycloak.adapters.authorization.spi.ConfigurationResolver; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; -import org.wildfly.security.http.oidc.OidcClientConfiguration; -import org.wildfly.security.http.oidc.OidcPrincipal; -import org.wildfly.security.http.oidc.RefreshableOidcSecurityContext; - -public class ElytronPolicyEnforcerFilter extends ServletPolicyEnforcerFilter { - - public ElytronPolicyEnforcerFilter(ConfigurationResolver configResolver) { - super(configResolver); - } - - @Override - protected String extractBearerToken(HttpServletRequest request) { - Principal principal = request.getUserPrincipal(); - - if (principal == null) { - return null; - } - - OidcPrincipal oidcPrincipal = (OidcPrincipal) principal; - RefreshableOidcSecurityContext securityContext = (RefreshableOidcSecurityContext) oidcPrincipal.getOidcSecurityContext(); - - if (securityContext == null) { - return null; - } - - return securityContext.getTokenString(); - } - - @Override - protected PolicyEnforcer createPolicyEnforcer(HttpServletRequest servletRequest, PolicyEnforcerConfig enforcerConfig) { - RefreshableOidcSecurityContext securityContext = (RefreshableOidcSecurityContext) ((OidcPrincipal) servletRequest.getUserPrincipal()).getOidcSecurityContext(); - OidcClientConfiguration configuration = securityContext.getOidcClientConfiguration(); - String authServerUrl = configuration.getAuthServerBaseUrl(); - - return PolicyEnforcer.builder() - .authServerUrl(authServerUrl) - .realm(configuration.getRealm()) - .clientId(configuration.getClientId()) - .credentials(configuration.getResourceCredentials()) - .bearerOnly(false) - .enforcerConfig(enforcerConfig) - .httpClient(configuration.getClient()).build(); - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/PolicyEnforcerServletContextListener.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/PolicyEnforcerServletContextListener.java deleted file mode 100644 index d5bec3b955..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/PolicyEnforcerServletContextListener.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.keycloak.adapters.authorization.integration.elytron; - -import java.io.IOException; -import java.io.InputStream; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.ServiceLoader; - -import jakarta.servlet.DispatcherType; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletContextEvent; -import jakarta.servlet.ServletContextListener; -import jakarta.servlet.annotation.WebListener; -import org.jboss.logging.Logger; -import org.keycloak.adapters.authorization.spi.ConfigurationResolver; -import org.keycloak.adapters.authorization.spi.HttpRequest; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; -import org.keycloak.util.JsonSerialization; - -/** - * A {@link ServletContextListener} to programmatically configure the {@link ServletContext} in order to - * enable the policy enforcer.

- * - * By default, the policy enforcer configuration is loaded from a file at {@code WEB-INF/policy-enforcer.json}.

- * - * Applications can also dynamically resolve the configuration by implementing the {@link ConfigurationResolver} SPI. For that, - * make sure to create a {@link META-INF/services/org.keycloak.adapters.authorization.spi.ConfigurationResolver} to register - * the implementation. - * - * @author Pedro Igor - */ -@WebListener -public class PolicyEnforcerServletContextListener implements ServletContextListener { - - private final Logger logger = Logger.getLogger(getClass()); - - @Override - public void contextInitialized(ServletContextEvent sce) { - ServletContext servletContext = sce.getServletContext(); - Iterator configResolvers = ServiceLoader.load(ConfigurationResolver.class).iterator(); - ConfigurationResolver configResolver; - - if (configResolvers.hasNext()) { - configResolver = configResolvers.next(); - - if (configResolvers.hasNext()) { - throw new IllegalStateException("Multiple " + ConfigurationResolver.class.getName() + " implementations found"); - } - - logger.debugf("Configuration resolver found from classpath: %s", configResolver); - } else { - String enforcerConfigLocation = "WEB-INF/policy-enforcer.json"; - InputStream config = servletContext.getResourceAsStream(enforcerConfigLocation); - - if (config == null) { - logger.debugf("Could not find the policy enforcer configuration file: %s", enforcerConfigLocation); - return; - } - - try { - configResolver = createDefaultConfigurationResolver(JsonSerialization.readValue(config, PolicyEnforcerConfig.class)); - } catch (IOException e) { - throw new RuntimeException("Failed to parse policy enforcer configuration: " + enforcerConfigLocation); - } - } - - logger.debug("Policy enforcement filter is enabled."); - - servletContext.addFilter("keycloak-policy-enforcer", new ElytronPolicyEnforcerFilter(configResolver)) - .addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*"); - } - - private ConfigurationResolver createDefaultConfigurationResolver(PolicyEnforcerConfig enforcerConfig) { - return new ConfigurationResolver() { - @Override - public PolicyEnforcerConfig resolve(HttpRequest request) { - return enforcerConfig; - } - }; - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ServletHttpRequest.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ServletHttpRequest.java deleted file mode 100644 index 6b645fce5e..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ServletHttpRequest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.adapters.authorization.integration.elytron; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import org.keycloak.adapters.authorization.TokenPrincipal; -import org.keycloak.adapters.authorization.spi.HttpRequest; - -/** - * @author Pedro Igor - */ -public class ServletHttpRequest implements HttpRequest { - - private final HttpServletRequest request; - private final TokenPrincipal tokenPrincipal; - private InputStream inputStream; - - public ServletHttpRequest(HttpServletRequest request, TokenPrincipal tokenPrincipal) { - this.request = request; - this.tokenPrincipal = tokenPrincipal; - } - - @Override - public String getRelativePath() { - String uri = request.getRequestURI(); - String contextPath = request.getContextPath(); - String servletPath = uri.substring(uri.indexOf(contextPath) + contextPath.length()); - - if ("".equals(servletPath)) { - servletPath = "/"; - } - - return servletPath; - } - - @Override - public String getMethod() { - return request.getMethod(); - } - - @Override - public String getURI() { - return request.getRequestURI(); - } - - @Override - public List getHeaders(String name) { - return Collections.list(request.getHeaders(name)); - } - - @Override - public String getFirstParam(String name) { - Map parameters = request.getParameterMap(); - String[] values = parameters.get(name); - - if (values == null || values.length == 0) { - return null; - } - - return values[0]; - } - - @Override - public String getCookieValue(String name) { - Cookie[] cookies = request.getCookies(); - - for (Cookie cookie : cookies) { - if (cookie.getName().equals(name)) { - return cookie.getValue(); - } - } - - return null; - } - - @Override - public String getRemoteAddr() { - return request.getRemoteAddr(); - } - - @Override - public boolean isSecure() { - return request.isSecure(); - } - - @Override - public String getHeader(String name) { - return request.getHeader(name); - } - - @Override - public InputStream getInputStream(boolean buffered) { - if (inputStream != null) { - return inputStream; - } - - if (buffered) { - try { - return inputStream = new BufferedInputStream(request.getInputStream()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - try { - return request.getInputStream(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public TokenPrincipal getPrincipal() { - return tokenPrincipal; - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ServletHttpResponse.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ServletHttpResponse.java deleted file mode 100644 index 9528224790..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/elytron/ServletHttpResponse.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.adapters.authorization.integration.elytron; - -import java.io.IOException; - -import jakarta.servlet.http.HttpServletResponse; -import org.keycloak.adapters.authorization.spi.HttpResponse; - -/** - * @author Pedro Igor - */ -public class ServletHttpResponse implements HttpResponse { - - private HttpServletResponse response; - - public ServletHttpResponse(HttpServletResponse response) { - this.response = response; - } - - @Override - public void sendError(int status) { - try { - response.sendError(status); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void sendError(int status, String reason) { - try { - response.sendError(status, reason); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void setHeader(String name, String value) { - response.setHeader(name, value); - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/jakarta/ServletPolicyEnforcerFilter.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/jakarta/ServletPolicyEnforcerFilter.java deleted file mode 100644 index ee0931044b..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/integration/jakarta/ServletPolicyEnforcerFilter.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.keycloak.adapters.authorization.integration.jakarta; - -import java.io.IOException; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletContextAttributeListener; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpSession; -import org.jboss.logging.Logger; -import org.keycloak.AuthorizationContext; -import org.keycloak.adapters.authorization.PolicyEnforcer; -import org.keycloak.adapters.authorization.TokenPrincipal; -import org.keycloak.adapters.authorization.integration.elytron.ServletHttpRequest; -import org.keycloak.adapters.authorization.integration.elytron.ServletHttpResponse; -import org.keycloak.adapters.authorization.spi.ConfigurationResolver; -import org.keycloak.adapters.authorization.spi.HttpRequest; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; -import org.wildfly.security.http.oidc.OidcClientConfiguration; -import org.wildfly.security.http.oidc.OidcPrincipal; -import org.wildfly.security.http.oidc.RefreshableOidcSecurityContext; - -/** - * A Jakarta Servlet {@link Filter} acting as a policy enforcer. This filter does not enforce access for anonymous subjects.

- * - * For authenticated subjects, this filter delegates the access decision to the {@link PolicyEnforcer} and decide if - * the request should continue.

- * - * If access is not granted, this filter aborts the request and relies on the {@link PolicyEnforcer} to properly - * respond to client. - * - * @author Pedro Igor - */ -public class ServletPolicyEnforcerFilter implements Filter, ServletContextAttributeListener { - - private final Logger logger = Logger.getLogger(getClass()); - private final Map policyEnforcer; - private final ConfigurationResolver configResolver; - - public ServletPolicyEnforcerFilter(ConfigurationResolver configResolver) { - this.configResolver = configResolver; - this.policyEnforcer = Collections.synchronizedMap(new HashMap<>()); - } - - @Override - public void init(FilterConfig filterConfig) { - // no-init - } - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - ServletHttpRequest httpRequest = new ServletHttpRequest(request, new TokenPrincipal() { - @Override - public String getRawToken() { - return extractBearerToken(request); - } - }); - - PolicyEnforcer policyEnforcer = getOrCreatePolicyEnforcer(request, httpRequest); - AuthorizationContext authzContext = policyEnforcer.enforce(httpRequest, new ServletHttpResponse(response)); - - request.setAttribute(AuthorizationContext.class.getName(), authzContext); - - if (authzContext.isGranted()) { - logger.debug("Request authorized, continuing the filter chain"); - filterChain.doFilter(servletRequest, servletResponse); - } else { - logger.debugf("Unauthorized request to path [%s], aborting the filter chain", request.getRequestURI()); - } - } - - protected String extractBearerToken(HttpServletRequest request) { - Enumeration authorizationHeaderValues = request.getHeaders("Authorization"); - - while (authorizationHeaderValues.hasMoreElements()) { - String value = authorizationHeaderValues.nextElement(); - String[] parts = value.trim().split("\\s+"); - - if (parts.length != 2) { - continue; - } - - String bearer = parts[0]; - - if (bearer.equalsIgnoreCase("Bearer")) { - return parts[1]; - } - } - - return null; - } - - private PolicyEnforcer getOrCreatePolicyEnforcer(HttpServletRequest servletRequest, HttpRequest request) { - return policyEnforcer.computeIfAbsent(configResolver.resolve(request), new Function() { - @Override - public PolicyEnforcer apply(PolicyEnforcerConfig enforcerConfig) { - return createPolicyEnforcer(servletRequest, enforcerConfig); - } - }); - } - - protected PolicyEnforcer createPolicyEnforcer(HttpServletRequest servletRequest, PolicyEnforcerConfig enforcerConfig) { - String authServerUrl = enforcerConfig.getAuthServerUrl(); - - return PolicyEnforcer.builder() - .authServerUrl(authServerUrl) - .realm(enforcerConfig.getRealm()) - .clientId(enforcerConfig.getResource()) - .credentials(enforcerConfig.getCredentials()) - .bearerOnly(false) - .enforcerConfig(enforcerConfig).build(); - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/ConfigurationResolver.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/ConfigurationResolver.java deleted file mode 100644 index 158d3f0922..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/ConfigurationResolver.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.adapters.authorization.spi; - -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; - -/** - * Resolves a {@link PolicyEnforcerConfig} based on the information from the {@link HttpRequest}.

- * - * @author Pedro Igor - */ -public interface ConfigurationResolver { - - /** - * Resolves a {@link PolicyEnforcerConfig} based on the information from the {@link HttpRequest}. - * - * @param request the request - * @return the policy enforcer configuration for the given request - */ - PolicyEnforcerConfig resolve(HttpRequest request); -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/HttpRequest.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/HttpRequest.java deleted file mode 100644 index 8fd0722488..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/HttpRequest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.adapters.authorization.spi; - -import java.io.InputStream; -import java.util.List; - -import org.keycloak.adapters.authorization.TokenPrincipal; - -/** - * Represents an incoming HTTP request and the contract to manipulate it. - * - * @author Pedro Igor - */ -public interface HttpRequest { - - /** - * Get the request path. This is the path relative to the context path. - * E.g.: for a HTTP GET request to http://my.appserver.com/my-application/path/sub-path this method is going to return /path/sub-path. - - * @return the relative path - */ - String getRelativePath(); - - /** - * Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT. - * - * @return a {@code String} specifying the name of the method with which this request was made - */ - String getMethod(); - - /** - * Get the URI representation for the current request. - * - * @return a {@code String} representation for the current request - */ - String getURI(); - - /** - * Get a list of all of the values set for the specified header within the HTTP request. - * - * @param name the header name - * @return a list of the values set for this header, if the header is not set on the request then null should be returned - */ - List getHeaders(String name); - - /** - * Get the first value for a parameter with the given {@code name} - * - * @param name the parameter name - * @return the value of the parameter - */ - String getFirstParam(String name); - - /** - * Get the first value for a cookie with the given {@code name}. - * - * @param name the parameter name - * @return the value of the cookie - */ - String getCookieValue(String name); - - /** - * Returns the client address. - * - * @return the client address. - */ - String getRemoteAddr(); - - /** - * Indicates if the request is coming from a secure channel through HTTPS. - * - * @return {@code true} if the HTTP scheme is set to 'https'. Otherwise, {@code false} - */ - boolean isSecure(); - - /** - * Get the first value for a HEADER with the given {@code name}. - * - * @param name the HEADER name - * @return the value of the HEADER - */ - String getHeader(String name); - - /** - * Returns the request input stream - * - * @param buffered if the input stream should be buffered and support for multiple reads - * @return the request input stream - */ - InputStream getInputStream(boolean buffered); - - /** - * Returns a {@link TokenPrincipal} associated with the request. - * - * @return the principal - */ - TokenPrincipal getPrincipal(); -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/HttpResponse.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/HttpResponse.java deleted file mode 100644 index dcd41a5f99..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/spi/HttpResponse.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.adapters.authorization.spi; - -/** - * Represents an outgoing HTTP response and the contract to manipulate it. - * - * @author Pedro Igor - */ -public interface HttpResponse { - - /** - * Send an error with the given {@code statusCode}. - * - * @param statusCode the status to set in the response - */ - void sendError(int statusCode); - - /** - * Send an error with the given {@code statusCode} and {@code reason} message. - * - * @param statusCode the status to set in the response - */ - void sendError(int statusCode, String reason); - - /** - * Set a header with the given {@code name} and {@code value}. - * - * @param name the header name - * @param value the header value - */ - void setHeader(String name, String value); -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/JsonUtils.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/JsonUtils.java deleted file mode 100644 index 5c06ca60b2..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/JsonUtils.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.util; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import com.fasterxml.jackson.databind.JsonNode; -import org.keycloak.jose.jws.JWSInput; -import org.keycloak.representations.AccessToken; -import org.keycloak.util.JsonSerialization; - -/** - * Utility methods to manipulate JSON data - * - * @author Pedro Igor - */ -public class JsonUtils { - - public static List getValues(JsonNode jsonNode, String path) { - return getValues(jsonNode.at(path)); - } - - public static List getValues(JsonNode jsonNode) { - List values = new ArrayList<>(); - - if (jsonNode.isArray()) { - for (JsonNode node : jsonNode) { - String value; - - if (node.isObject()) { - try { - value = JsonSerialization.writeValueAsString(node); - } catch (IOException e) { - throw new RuntimeException(e); - } - } else { - value = node.asText(); - } - - if (value != null) { - values.add(value); - } - } - } else { - String value = jsonNode.asText(); - - if (value != null) { - values.add(value); - } - } - - return values; - } - - public static AccessToken asAccessToken(String rawToken) { - try { - return new JWSInput(rawToken).readJsonContent(AccessToken.class); - } catch (Exception cause) { - throw new RuntimeException("Failed to decode token", cause); - } - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/KeycloakSecurityContextPlaceHolderResolver.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/KeycloakSecurityContextPlaceHolderResolver.java deleted file mode 100644 index b5f824ad9a..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/KeycloakSecurityContextPlaceHolderResolver.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.util; - -import static org.keycloak.adapters.authorization.util.PlaceHolders.getParameter; - -import java.util.Arrays; -import java.util.List; - -import com.fasterxml.jackson.databind.JsonNode; -import org.keycloak.adapters.authorization.TokenPrincipal; -import org.keycloak.adapters.authorization.spi.HttpRequest; -import org.keycloak.util.JsonSerialization; - -/** - * @author Pedro Igor - */ -public class KeycloakSecurityContextPlaceHolderResolver implements PlaceHolderResolver { - - public static final String NAME = "keycloak"; - - @Override - public List resolve(String placeHolder, HttpRequest request) { - String source = placeHolder.substring(placeHolder.indexOf('.') + 1); - TokenPrincipal principal = request.getPrincipal(); - - if (source.endsWith("access_token")) { - return Arrays.asList(principal.getRawToken()); - } - - JsonNode jsonNode; - - if (source.startsWith("access_token[")) { - jsonNode = JsonSerialization.mapper.valueToTree(principal.getToken()); - } else { - throw new RuntimeException("Invalid placeholder [" + placeHolder + "]"); - } - - return JsonUtils.getValues(jsonNode, getParameter(source, "Invalid placeholder [" + placeHolder + "]")); - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/PlaceHolderResolver.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/PlaceHolderResolver.java deleted file mode 100644 index 935fc47db1..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/PlaceHolderResolver.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.util; - -import java.util.List; - -import org.keycloak.adapters.authorization.spi.HttpRequest; - -/** - * @author Pedro Igor - */ -public interface PlaceHolderResolver { - - List resolve(String placeHolder, HttpRequest httpFacade); - -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/PlaceHolders.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/PlaceHolders.java deleted file mode 100644 index d7a4f5f479..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/PlaceHolders.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.util; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.keycloak.adapters.authorization.spi.HttpRequest; - -/** - * @author Pedro Igor - */ -public class PlaceHolders { - - private static Map resolvers = new HashMap<>(); - - static { - resolvers.put(RequestPlaceHolderResolver.NAME, new RequestPlaceHolderResolver()); - resolvers.put(KeycloakSecurityContextPlaceHolderResolver.NAME, new KeycloakSecurityContextPlaceHolderResolver()); - } - - private static Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{(.+?)\\}"); - private static Pattern PLACEHOLDER_PARAM_PATTERN = Pattern.compile("\\[(.+?)\\]"); - - public static List resolve(String value, HttpRequest httpFacade) { - Map> placeHolders = parsePlaceHolders(value, httpFacade); - - if (!placeHolders.isEmpty()) { - value = formatPlaceHolder(value); - - for (Entry> entry : placeHolders.entrySet()) { - List values = entry.getValue(); - - if (values.isEmpty() || values.size() > 1) { - return values; - } - - value = value.replaceAll(entry.getKey(), values.get(0)).trim(); - } - } - - return Arrays.asList(value); - } - - static String getParameter(String source, String messageIfNotFound) { - Matcher matcher = PLACEHOLDER_PARAM_PATTERN.matcher(source); - - while (matcher.find()) { - return matcher.group(1).replaceAll("'", ""); - } - - if (messageIfNotFound != null) { - throw new RuntimeException(messageIfNotFound); - } - - return null; - } - - private static Map> parsePlaceHolders(String value, HttpRequest httpFacade) { - Map> placeHolders = Collections.emptyMap(); - Matcher matcher = PLACEHOLDER_PATTERN.matcher(value); - boolean found = matcher.find(); - - if (found) { - placeHolders = new HashMap<>(); - do { - String placeHolder = matcher.group(1); - int resolverNameIdx = placeHolder.indexOf('.'); - - if (resolverNameIdx == -1) { - throw new RuntimeException("Invalid placeholder [" + value + "]. Could not find resolver name."); - } - - PlaceHolderResolver resolver = resolvers.get(placeHolder.substring(0, resolverNameIdx)); - - if (resolver != null) { - List resolved = resolver.resolve(placeHolder, httpFacade); - - if (resolved != null) { - placeHolders.put(formatPlaceHolder(placeHolder), resolved); - } - } - } while (matcher.find()); - } - - return placeHolders; - } - - private static String formatPlaceHolder(String placeHolder) { - return placeHolder.replaceAll("\\{", "").replace("}", "").replace("[", "").replace("]", "").replace("[", "").replace("]", ""); - } -} diff --git a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/RequestPlaceHolderResolver.java b/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/RequestPlaceHolderResolver.java deleted file mode 100644 index 5d49625e99..0000000000 --- a/authz/policy-enforcer/src/main/java/org/keycloak/adapters/authorization/util/RequestPlaceHolderResolver.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.adapters.authorization.util; - -import static org.keycloak.adapters.authorization.util.PlaceHolders.getParameter; - -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import com.fasterxml.jackson.databind.JsonNode; -import org.keycloak.adapters.authorization.spi.HttpRequest; -import org.keycloak.util.JsonSerialization; - -/** - * @author Pedro Igor - */ -public class RequestPlaceHolderResolver implements PlaceHolderResolver { - - static String NAME = "request"; - - @Override - public List resolve(String placeHolder, HttpRequest request) { - String source = placeHolder.substring(placeHolder.indexOf('.') + 1); - - if (source.startsWith("parameter")) { - String parameterName = getParameter(source, "Could not obtain parameter name from placeholder [" + source + "]"); - String parameterValue = request.getFirstParam(parameterName); - - if (parameterValue != null) { - return Arrays.asList(parameterValue); - } - } else if (source.startsWith("header")) { - String headerName = getParameter(source, "Could not obtain header name from placeholder [" + source + "]"); - List headerValue = request.getHeaders(headerName); - - if (headerValue != null) { - return headerValue; - } - } else if (source.startsWith("cookie")) { - String cookieName = getParameter(source, "Could not obtain cookie name from placeholder [" + source + "]"); - String cookieValue = request.getCookieValue(cookieName); - - if (cookieValue != null) { - return Arrays.asList(cookieValue); - } - } else if (source.startsWith("remoteAddr")) { - String value = request.getRemoteAddr(); - - if (value != null) { - return Arrays.asList(value); - } - } else if (source.startsWith("method")) { - String value = request.getMethod(); - - if (value != null) { - return Arrays.asList(value); - } - } else if (source.startsWith("uri")) { - String value = request.getURI(); - - if (value != null) { - return Arrays.asList(value); - } - } else if (source.startsWith("relativePath")) { - String value = request.getRelativePath(); - - if (value != null) { - return Arrays.asList(value); - } - } else if (source.startsWith("secure")) { - return Arrays.asList(String.valueOf(request.isSecure())); - } else if (source.startsWith("body")) { - String contentType = request.getHeader("Content-Type"); - - if (contentType == null) { - contentType = ""; - } else if (contentType.indexOf(';') != -1){ - contentType = contentType.substring(0, contentType.indexOf(';')).trim(); - } - - InputStream body = request.getInputStream(true); - - try { - if (body == null || body.available() == 0) { - return Collections.emptyList(); - } - } catch (IOException cause) { - throw new RuntimeException("Failed to check available bytes in request input stream", cause); - } - - if (body.markSupported()) { - body.mark(0); - } - - List values = new ArrayList<>(); - - try { - switch (contentType) { - case "application/json": - try { - JsonNode jsonNode = JsonSerialization.mapper.readTree(new BufferedInputStream(body) { - @Override - public void close() { - // we can't close the stream because it may be used later by the application - } - }); - String path = getParameter(source, null); - - if (path == null) { - values.addAll(JsonUtils.getValues(jsonNode)); - } else { - values.addAll(JsonUtils.getValues(jsonNode, path)); - } - } catch (IOException cause) { - throw new RuntimeException("Could not extract claim from request JSON body", cause); - } - break; - default: - StringBuilder value = new StringBuilder(); - BufferedReader reader = new BufferedReader(new InputStreamReader(body)); - - try { - int ch; - - while ((ch = reader.read()) != -1) { - value.append((char) ch); - } - } catch (IOException cause) { - throw new RuntimeException("Could not extract claim from request body", cause); - } - - values.add(value.toString()); - } - } finally { - if (body.markSupported()) { - try { - body.reset(); - } catch (IOException cause) { - throw new RuntimeException("Failed to reset request input stream", cause); - } - } - } - - return values; - } - - return Collections.emptyList(); - } -} diff --git a/authz/policy-enforcer/src/main/resources/META-INF/services/org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory b/authz/policy-enforcer/src/main/resources/META-INF/services/org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory deleted file mode 100644 index f40afedf26..0000000000 --- a/authz/policy-enforcer/src/main/resources/META-INF/services/org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory +++ /dev/null @@ -1,19 +0,0 @@ -# -# * Copyright 2018 Red Hat, Inc. and/or its affiliates -# * and other contributors as indicated by the @author tags. -# * -# * Licensed under the Apache License, Version 2.0 (the "License"); -# * you may not use this file except in compliance with the License. -# * You may obtain a copy of the License at -# * -# * http://www.apache.org/licenses/LICENSE-2.0 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# - -org.keycloak.adapters.authorization.cip.ClaimsInformationPointProviderFactory -org.keycloak.adapters.authorization.cip.HttpClaimInformationPointProviderFactory \ No newline at end of file diff --git a/authz/pom.xml b/authz/pom.xml index 31224da503..711d68b471 100644 --- a/authz/pom.xml +++ b/authz/pom.xml @@ -20,6 +20,5 @@ policy client - policy-enforcer \ No newline at end of file diff --git a/pom.xml b/pom.xml index 65300a6088..5d2d2199fc 100644 --- a/pom.xml +++ b/pom.xml @@ -1052,11 +1052,6 @@ keycloak-authz-policy-common ${project.version} - - org.keycloak - keycloak-policy-enforcer-tests - ${project.version} - diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/AuthzTestUtils.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/AuthzTestUtils.java deleted file mode 100644 index d5bfc3f6ba..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/AuthzTestUtils.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2024 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.keycloak.testsuite.util; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Scanner; -import org.keycloak.adapters.authorization.PolicyEnforcer; -import org.keycloak.adapters.authorization.TokenPrincipal; -import org.keycloak.adapters.authorization.spi.HttpRequest; -import org.keycloak.adapters.authorization.spi.HttpResponse; - -/** - * - * @author rmartinc - */ -public class AuthzTestUtils { - - private AuthzTestUtils() { - } - - public static InputStream httpsAwareConfigurationStream(InputStream input) throws IOException { - if (!ServerURLs.AUTH_SERVER_SSL_REQUIRED) { - return input; - } - final ByteArrayOutputStream out = new ByteArrayOutputStream(); - try (PrintWriter pw = new PrintWriter(out); - Scanner s = new Scanner(input)) { - while (s.hasNextLine()) { - String lineWithReplaces = s.nextLine().replace("http://localhost:8180/auth", - ServerURLs.AUTH_SERVER_SCHEME + "://localhost:" + ServerURLs.AUTH_SERVER_PORT + "/auth"); - pw.println(lineWithReplaces); - } - } - return new ByteArrayInputStream(out.toByteArray()); - } - - public static InputStream getAdapterConfiguration(String fileName) { - try { - return httpsAwareConfigurationStream(AuthzTestUtils.class.getResourceAsStream("/authorization-test/" + fileName)); - } catch (IOException e) { - throw new AssertionError("Could not load keycloak configuration", e); - } - } - - public static PolicyEnforcer createPolicyEnforcer(String resource, boolean bearerOnly) { - try (InputStream is = getAdapterConfiguration(resource)) { - return PolicyEnforcer.builder().enforcerConfig(is).bearerOnly(bearerOnly).build(); - } catch (IOException e) { - throw new IllegalArgumentException("Invalid resource " + resource, e); - } - } - - public static HttpRequest createHttpRequest(String path) { - return createHttpRequest(path, null, null, null, Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), null); - } - - public static HttpRequest createHttpRequest(String path, String token) { - return createHttpRequest(path, null, null, token, Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), null); - } - - public static HttpRequest createHttpRequest(String path, String token, String method) { - return createHttpRequest(path, null, method, token, Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), null); - } - - public static HttpRequest createHttpRequest(String path, String token, Map> parameters) { - return createHttpRequest(path, null, null, token, Collections.emptyMap(), parameters, Collections.emptyMap(), null); - } - - public static HttpRequest createHttpRequest(String path, String method, String token, Map> headers, Map> parameters, InputStream requestBody) { - return createHttpRequest(path, null, method, token, headers, parameters, Collections.emptyMap(), null); - } - - public static HttpRequest createHttpRequest(String path, String relativePath, String method, String token, Map> headers, Map> parameters, Map cookies, InputStream requestBody) { - return new HttpRequest() { - - private InputStream inputStream; - - @Override - public String getRelativePath() { - return relativePath != null? relativePath : path; - } - - @Override - public String getMethod() { - return method == null ? "GET" : method; - } - - @Override - public String getURI() { - return path; - } - - @Override - public List getHeaders(String name) { - return headers.getOrDefault(name, Collections.emptyList()); - } - - @Override - public String getFirstParam(String name) { - List values = parameters.getOrDefault(name, Collections.emptyList()); - return values.isEmpty()? null : values.iterator().next(); - } - - @Override - public String getCookieValue(String name) { - return cookies.get(name); - } - - @Override - public String getRemoteAddr() { - return "user-remote-addr"; - } - - @Override - public boolean isSecure() { - return true; - } - - @Override - public String getHeader(String name) { - List headers = getHeaders(name); - return headers.isEmpty()? null : headers.iterator().next(); - } - - @Override - public InputStream getInputStream(boolean buffered) { - if (requestBody == null) { - return new ByteArrayInputStream(new byte[] {}); - } - - if (inputStream != null) { - return inputStream; - } - - if (buffered) { - return inputStream = new BufferedInputStream(requestBody); - } - - return requestBody; - } - - @Override - public TokenPrincipal getPrincipal() { - return () -> token; - } - }; - } - - public static class TestResponse implements HttpResponse { - - private final Map> headers; - private int status; - - public TestResponse() { - this.headers = new HashMap<>(); - } - - public TestResponse(Map> headers) { - this.headers = headers; - } - - public int getStatus() { - return status; - } - - @Override - public void setHeader(String name, String value) { - headers.put(name, Arrays.asList(value)); - } - - public Map> getHeaders() { - return headers; - } - - @Override - public void sendError(int code) { - status = code; - } - - @Override - public void sendError(int code, String message) { - status = code; - } - - public TestResponse clear() { - this.status = -1; - this.headers.clear(); - return this; - } - } -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthzClientCredentialsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthzClientCredentialsTest.java index d3b0120da5..0e49d344ea 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthzClientCredentialsTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthzClientCredentialsTest.java @@ -23,14 +23,15 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.IOException; import java.io.InputStream; +import java.io.UncheckedIOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.junit.Before; import org.junit.Test; -import org.keycloak.adapters.authorization.PolicyEnforcer; import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.resource.AuthorizationResource; import org.keycloak.admin.client.resource.ClientResource; @@ -38,6 +39,7 @@ import org.keycloak.admin.client.resource.ClientsResource; import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator; import org.keycloak.authentication.authenticators.client.JWTClientSecretAuthenticator; import org.keycloak.authorization.client.AuthzClient; +import org.keycloak.authorization.client.Configuration; import org.keycloak.authorization.client.resource.ProtectionResource; import org.keycloak.authorization.client.util.HttpResponseException; import org.keycloak.common.util.Time; @@ -60,6 +62,7 @@ import org.keycloak.testsuite.util.ClientBuilder; import org.keycloak.testsuite.util.RealmBuilder; import org.keycloak.testsuite.util.RolesBuilder; import org.keycloak.testsuite.util.UserBuilder; +import org.keycloak.util.JsonSerialization; /** * @author Bill Burke @@ -308,12 +311,12 @@ public class AuthzClientCredentialsTest extends AbstractAuthzTest { public void testFindByName() { AuthzClient authzClient = getAuthzClient("default-session-keycloak.json"); ProtectionResource protection = authzClient.protection(); - + protection.resource().create(new ResourceRepresentation("Admin Resources")); protection.resource().create(new ResourceRepresentation("Resource")); ResourceRepresentation resource = authzClient.protection().resource().findByName("Resource"); - + assertEquals("Resource", resource.getName()); ResourceRepresentation adminResource = authzClient.protection().resource().findByName("Admin Resources"); @@ -346,9 +349,12 @@ public class AuthzClientCredentialsTest extends AbstractAuthzTest { } private AuthzClient getAuthzClient(String adapterConfig) { - PolicyEnforcer policyEnforcer = PolicyEnforcer.builder().enforcerConfig(getConfigurationStream(adapterConfig)).build(); - - return policyEnforcer.getAuthzClient(); + try { + Configuration authzClientConfig = JsonSerialization.readValue(getConfigurationStream(adapterConfig), Configuration.class); + return AuthzClient.create(authzClientConfig); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } } private InputStream getConfigurationStream(String adapterConfig) { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/ClaimInformationPointProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/ClaimInformationPointProviderTest.java deleted file mode 100644 index 71faf82c29..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/ClaimInformationPointProviderTest.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.authz.admin; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.keycloak.common.Profile.Feature.AUTHORIZATION; -import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.undertow.Undertow; -import io.undertow.server.handlers.form.FormData; -import io.undertow.server.handlers.form.FormDataParser; -import io.undertow.server.handlers.form.FormParserFactory; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProvider; -import org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory; -import org.keycloak.adapters.authorization.PolicyEnforcer; -import org.keycloak.adapters.authorization.spi.HttpRequest; -import org.keycloak.jose.jws.JWSBuilder; -import org.keycloak.representations.AccessToken; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.testsuite.AbstractKeycloakTest; -import org.keycloak.testsuite.ProfileAssume; -import org.keycloak.testsuite.util.AuthzTestUtils; -import org.keycloak.util.JsonSerialization; - -/** - * @author Pedro Igor - */ -public class ClaimInformationPointProviderTest extends AbstractKeycloakTest { - - private static Undertow httpService; - - @BeforeClass - public static void enabled() { - ProfileAssume.assumeFeatureEnabled(AUTHORIZATION); - } - - @BeforeClass - public static void onBeforeClass() { - httpService = Undertow.builder().addHttpListener(8989, "localhost").setHandler(exchange -> { - if (exchange.isInIoThread()) { - try { - if (exchange.getRelativePath().equals("/post-claim-information-provider")) { - FormParserFactory parserFactory = FormParserFactory.builder().build(); - FormDataParser parser = parserFactory.createParser(exchange); - FormData formData = parser.parseBlocking(); - - if (!("Bearer " + accessTokenString()).equals(exchange.getRequestHeaders().getFirst("Authorization")) - || !"post".equalsIgnoreCase(exchange.getRequestMethod().toString()) - || !"application/x-www-form-urlencoded".equals(exchange.getRequestHeaders().getFirst("Content-Type")) - || !exchange.getRequestHeaders().get("header-b").contains("header-b-value1") - || !exchange.getRequestHeaders().get("header-b").contains("header-b-value2") - || !formData.get("param-a").getFirst().getValue().equals("param-a-value1") - || !formData.get("param-a").getLast().getValue().equals("param-a-value2") - || !formData.get("param-subject").getFirst().getValue().equals("sub") - || !formData.get("param-user-name").getFirst().getValue().equals("username") - || !formData.get("param-other-claims").getFirst().getValue().equals("param-other-claims-value1") - || !formData.get("param-other-claims").getLast().getValue().equals("param-other-claims-value2")) { - exchange.setStatusCode(400); - return; - } - - exchange.setStatusCode(200); - } else if (exchange.getRelativePath().equals("/get-claim-information-provider")) { - if (!("Bearer " + accessTokenString()).equals(exchange.getRequestHeaders().getFirst("Authorization")) - || !"get".equalsIgnoreCase(exchange.getRequestMethod().toString()) - || !exchange.getRequestHeaders().get("header-b").contains("header-b-value1") - || !exchange.getRequestHeaders().get("header-b").contains("header-b-value2") - || !exchange.getQueryParameters().get("param-a").contains("param-a-value1") - || !exchange.getQueryParameters().get("param-a").contains("param-a-value2") - || !exchange.getQueryParameters().get("param-subject").contains("sub") - || !exchange.getQueryParameters().get("param-user-name").contains("username")) { - exchange.setStatusCode(400); - return; - } - - exchange.setStatusCode(200); - } else { - exchange.setStatusCode(404); - } - } finally { - if (exchange.getStatusCode() == 200) { - try { - ObjectMapper mapper = JsonSerialization.mapper; - JsonParser jsonParser = mapper.getFactory().createParser("{\"a\": \"a-value1\", \"b\": \"b-value1\", \"d\": [\"d-value1\", \"d-value2\"]}"); - TreeNode treeNode = mapper.readTree(jsonParser); - exchange.getResponseSender().send(treeNode.toString()); - } catch (Exception ignore) { - ignore.printStackTrace(); - } - } - exchange.endExchange(); - } - } - }).build(); - - httpService.start(); - } - - @AfterClass - public static void onAfterClass() { - if (httpService != null) { - httpService.stop(); - } - } - - @Override - public void addTestRealms(List testRealms) { - RealmRepresentation realm = loadRealm(getClass().getResourceAsStream("/authorization-test/test-authz-realm.json")); - testRealms.add(realm); - } - - private ClaimInformationPointProvider getClaimInformationProviderForPath(String path, String providerName) { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-config-claims-provider.json", true); - Map providers = policyEnforcer.getClaimInformationPointProviderFactories(); - - PathConfig pathConfig = policyEnforcer.getPaths().get(path); - - assertNotNull(pathConfig); - - Map> cipConfig = pathConfig.getClaimInformationPointConfig(); - - assertNotNull(cipConfig); - - ClaimInformationPointProviderFactory factory = providers.get(providerName); - - assertNotNull(factory); - - Map claimsConfig = cipConfig.get(providerName); - - return factory.create(claimsConfig); - } - - @Test - public void testBasicClaimsInformationPoint() { - Map> claims = getClaimInformationProviderForPath("/claims-provider", "claims") - .resolve(createHttpRequest()); - - assertEquals("parameter-a", claims.get("claim-from-request-parameter").get(0)); - assertEquals("header-b", claims.get("claim-from-header").get(0)); - assertEquals("cookie-c", claims.get("claim-from-cookie").get(0)); - assertEquals("user-remote-addr", claims.get("claim-from-remoteAddr").get(0)); - assertEquals("GET", claims.get("claim-from-method").get(0)); - assertEquals("/app/request-uri", claims.get("claim-from-uri").get(0)); - assertEquals("/request-relative-path", claims.get("claim-from-relativePath").get(0)); - assertEquals("true", claims.get("claim-from-secure").get(0)); - assertEquals("static value", claims.get("claim-from-static-value").get(0)); - assertEquals("static", claims.get("claim-from-multiple-static-value").get(0)); - assertEquals("value", claims.get("claim-from-multiple-static-value").get(1)); - assertEquals("Test param-other-claims-value1 and parameter-a", claims.get("param-replace-multiple-placeholder").get(0)); - } - - @Test - public void testBodyJsonClaimsInformationPoint() throws Exception { - Map> headers = new HashMap<>(); - - headers.put("Content-Type", Arrays.asList("application/json")); - - ObjectMapper mapper = JsonSerialization.mapper; - JsonParser parser = mapper.getFactory().createParser("{\"a\": {\"b\": {\"c\": \"c-value\"}}, \"d\": [\"d-value1\", \"d-value2\"], \"e\": {\"number\": 123}}"); - TreeNode treeNode = mapper.readTree(parser); - - Map> claims = getClaimInformationProviderForPath("/claims-provider", "claims").resolve( - createHttpRequest(headers, new ByteArrayInputStream(treeNode.toString().getBytes()))); - - assertEquals("c-value", claims.get("claim-from-json-body-object").get(0)); - assertEquals("d-value2", claims.get("claim-from-json-body-array").get(0)); - assertEquals("123", claims.get("claim-from-json-body-number").get(0)); - } - - @Test - public void testBodyJsonObjectClaim() throws Exception { - Map> headers = new HashMap<>(); - - headers.put("Content-Type", Arrays.asList("application/json")); - - ObjectMapper mapper = JsonSerialization.mapper; - JsonParser parser = mapper.getFactory().createParser("{\"Individual\" : {\n" - + "\n" - + " \"Name\": \"John\",\n" - + "\n" - + " \"Lastname\": \"Doe\",\n" - + "\n" - + " \"individualRoles\" : [ {\n" - + "\n" - + " \"roleSpec\": 2342,\n" - + "\n" - + " \"roleId\": 4234},\n" - + "\n" - + "{\n" - + "\n" - + " \"roleSpec\": 4223,\n" - + "\n" - + " \"roleId\": 523\n" - + "\n" - + " }\n" - + "\n" - + " ]\n" - + "\n" - + "}}"); - TreeNode treeNode = mapper.readTree(parser); - - Map> claims = getClaimInformationProviderForPath("/claims-from-body-json-object", "claims") - .resolve(createHttpRequest(headers, new ByteArrayInputStream(treeNode.toString().getBytes()))); - - assertEquals(1, claims.size()); - assertEquals(2, claims.get("individualRoles").size()); - assertEquals("{\"roleSpec\":2342,\"roleId\":4234}", claims.get("individualRoles").get(0)); - assertEquals("{\"roleSpec\":4223,\"roleId\":523}", claims.get("individualRoles").get(1)); - - headers.put("Content-Type", Arrays.asList("application/json; charset=utf-8")); - - claims = getClaimInformationProviderForPath("/claims-from-body-json-object", "claims") - .resolve(createHttpRequest(headers, new ByteArrayInputStream(treeNode.toString().getBytes()))); - - assertEquals(1, claims.size()); - assertEquals(2, claims.get("individualRoles").size()); - assertEquals("{\"roleSpec\":2342,\"roleId\":4234}", claims.get("individualRoles").get(0)); - assertEquals("{\"roleSpec\":4223,\"roleId\":523}", claims.get("individualRoles").get(1)); - } - - @Test - public void testBodyClaimsInformationPoint() { - Map> claims = getClaimInformationProviderForPath("/claims-provider", "claims") - .resolve(createHttpRequest(new HashMap<>(), new ByteArrayInputStream("raw-body-text".getBytes()))); - - assertEquals("raw-body-text", claims.get("claim-from-body").get(0)); - } - - @Test - public void testHttpClaimInformationPointProviderWithoutClaims() { - Map> claims = getClaimInformationProviderForPath("/http-get-claim-provider", "http") - .resolve(createHttpRequest(new HashMap<>(), null)); - - assertEquals("a-value1", claims.get("a").get(0)); - assertEquals("b-value1", claims.get("b").get(0)); - assertEquals("d-value1", claims.get("d").get(0)); - assertEquals("d-value2", claims.get("d").get(1)); - - assertNull(claims.get("claim-a")); - assertNull(claims.get("claim-d")); - assertNull(claims.get("claim-d0")); - assertNull(claims.get("claim-d-all")); - } - - @Test - public void testHttpClaimInformationPointProviderWithClaims() { - Map> claims = getClaimInformationProviderForPath("/http-post-claim-provider", "http") - .resolve(createHttpRequest(new HashMap<>(), null)); - - assertEquals("a-value1", claims.get("claim-a").get(0)); - assertEquals("d-value1", claims.get("claim-d").get(0)); - assertEquals("d-value2", claims.get("claim-d").get(1)); - assertEquals("d-value1", claims.get("claim-d0").get(0)); - assertEquals("d-value1", claims.get("claim-d-all").get(0)); - assertEquals("d-value2", claims.get("claim-d-all").get(1)); - - assertNull(claims.get("a")); - assertNull(claims.get("b")); - assertNull(claims.get("d")); - } - - private static HttpRequest createHttpRequest() { - return createHttpRequest(new HashMap<>(), null); - } - - private static HttpRequest createHttpRequest(Map> headers, InputStream requestBody) { - Map> queryParameter = new HashMap<>(); - queryParameter.put("a", Arrays.asList("parameter-a")); - headers.put("b", Arrays.asList("header-b")); - Map cookies = new HashMap<>(); - cookies.put("c", "cookie-c"); - return AuthzTestUtils.createHttpRequest("/app/request-uri", "/request-relative-path", "GET", - accessTokenString(), headers, queryParameter, cookies, requestBody); - } - - private static AccessToken accessToken() { - AccessToken token = new AccessToken(); - token.subject("sub"); - token.setPreferredUsername("username"); - token.getOtherClaims().put("custom_claim", Arrays.asList("param-other-claims-value1", "param-other-claims-value2")); - return token; - } - - private static String accessTokenString() { - return new JWSBuilder().jsonContent(accessToken()).none(); - } -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/EnforcerConfigTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/EnforcerConfigTest.java deleted file mode 100644 index a352def249..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/EnforcerConfigTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.authz.admin; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.keycloak.adapters.authorization.PolicyEnforcer; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.testsuite.AbstractKeycloakTest; -import org.keycloak.testsuite.util.AuthzTestUtils; - -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.keycloak.testsuite.ProfileAssume; - -import static org.keycloak.common.Profile.Feature.AUTHORIZATION; -import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm; - -/** - * @author Pedro Igor - */ -public class EnforcerConfigTest extends AbstractKeycloakTest { - - @BeforeClass - public static void enabled() { - ProfileAssume.assumeFeatureEnabled(AUTHORIZATION); - } - - @Override - public void addTestRealms(List testRealms) { - RealmRepresentation realm = loadRealm(getClass().getResourceAsStream("/authorization-test/test-authz-realm.json")); - testRealms.add(realm); - } - - @Test - public void testMultiplePathsWithSameName() { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-config-paths-same-name.json", true); - Map paths = policyEnforcer.getPaths(); - assertEquals(1, paths.size()); - assertEquals(4, paths.values().iterator().next().getMethods().size()); - } - - @Test - public void testPathConfigClaimInformationPoint() { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-config-path-cip.json", true); - Map paths = policyEnforcer.getPaths(); - - assertEquals(1, paths.size()); - - PathConfig pathConfig = paths.values().iterator().next(); - Map> cipConfig = pathConfig.getClaimInformationPointConfig(); - - assertEquals(1, cipConfig.size()); - - Map claims = cipConfig.get("claims"); - - assertNotNull(claims); - - assertEquals(3, claims.size()); - assertEquals("{request.parameter['a']}", claims.get("claim-a")); - assertEquals("{request.header['b']}", claims.get("claim-b")); - assertEquals("{request.cookie['c']}", claims.get("claim-c")); - } -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/MyCustomCIPFactory.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/MyCustomCIPFactory.java deleted file mode 100644 index 6d603da181..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/MyCustomCIPFactory.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.authz.admin; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProvider; -import org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory; -import org.keycloak.adapters.authorization.spi.HttpRequest; - -public class MyCustomCIPFactory implements ClaimInformationPointProviderFactory { - - @Override - public String getName() { - return "my-custom-cip"; - } - - @Override - public MyCustomCIP create(Map config) { - return new MyCustomCIP(config); - } -} - -class MyCustomCIP implements ClaimInformationPointProvider { - - private final Map config; - - MyCustomCIP(Map config) { - this.config = config; - } - - @Override - public Map> resolve(HttpRequest request) { - Map> claims = new HashMap<>(); - - claims.put("resolved-claim", Arrays.asList(config.get("claim-value").toString())); - - return claims; - } -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/PolicyEnforcerClaimsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/PolicyEnforcerClaimsTest.java deleted file mode 100644 index 6a2f1e7135..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/PolicyEnforcerClaimsTest.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.authz.admin; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.keycloak.common.Profile.Feature.AUTHORIZATION; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.keycloak.AuthorizationContext; -import org.keycloak.OAuth2Constants; -import org.keycloak.adapters.authorization.PolicyEnforcer; -import org.keycloak.admin.client.resource.ClientResource; -import org.keycloak.admin.client.resource.ClientsResource; -import org.keycloak.authorization.client.AuthzClient; -import org.keycloak.representations.idm.ClientRepresentation; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.representations.idm.authorization.AuthorizationRequest; -import org.keycloak.representations.idm.authorization.AuthorizationResponse; -import org.keycloak.representations.idm.authorization.JSPolicyRepresentation; -import org.keycloak.representations.idm.authorization.Permission; -import org.keycloak.representations.idm.authorization.ResourceRepresentation; -import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation; -import org.keycloak.representations.idm.authorization.ScopeRepresentation; -import org.keycloak.testsuite.AbstractKeycloakTest; -import org.keycloak.testsuite.ProfileAssume; -import org.keycloak.testsuite.util.AuthzTestUtils; -import org.keycloak.testsuite.util.ClientBuilder; -import org.keycloak.testsuite.util.OAuthClient; -import org.keycloak.testsuite.util.RealmBuilder; -import org.keycloak.testsuite.util.RoleBuilder; -import org.keycloak.testsuite.util.RolesBuilder; -import org.keycloak.testsuite.util.UserBuilder; - -/** - * @author Pedro Igor - */ -public class PolicyEnforcerClaimsTest extends AbstractKeycloakTest { - - protected static final String REALM_NAME = "authz-test"; - - @BeforeClass - public static void enabled() { - ProfileAssume.assumeFeatureEnabled(AUTHORIZATION); - } - - @Override - public void addTestRealms(List testRealms) { - testRealms.add(RealmBuilder.create().name(REALM_NAME) - .roles(RolesBuilder.create() - .realmRole(RoleBuilder.create().name("uma_authorization").build()) - .realmRole(RoleBuilder.create().name("uma_protection").build()) - ) - .user(UserBuilder.create().username("marta").password("password") - .addRoles("uma_authorization", "uma_protection") - .role("resource-server-test", "uma_protection")) - .user(UserBuilder.create().username("kolo").password("password")) - .client(ClientBuilder.create().clientId("resource-server-uma-test") - .secret("secret") - .authorizationServicesEnabled(true) - .redirectUris("http://localhost/resource-server-uma-test") - .defaultRoles("uma_protection") - .directAccessGrants()) - .client(ClientBuilder.create().clientId("resource-server-test") - .secret("secret") - .authorizationServicesEnabled(true) - .redirectUris("http://localhost/resource-server-test") - .defaultRoles("uma_protection") - .directAccessGrants()) - .client(ClientBuilder.create().clientId("public-client-test") - .publicClient() - .redirectUris("http://localhost:8180/auth/realms/master/app/auth/*", "https://localhost:8543/auth/realms/master/app/auth/*") - .directAccessGrants()) - .build()); - } - - @Test - public void testEnforceUMAAccessWithClaimsUsingBearerToken() { - initAuthorizationSettings(getClientResource("resource-server-uma-test")); - - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-uma-claims-test.json", true); - HashMap> headers = new HashMap<>(); - HashMap> parameters = new HashMap<>(); - - parameters.put("withdrawal.amount", Arrays.asList("50")); - - AuthzClient authzClient = policyEnforcer.getAuthzClient(); - String token = authzClient.obtainAccessToken("marta", "password").getToken(); - - headers.put("Authorization", Arrays.asList("Bearer " + token)); - - AuthzTestUtils.TestResponse testResponse = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", "POST", token, headers, parameters, null), - testResponse); - assertFalse(context.isGranted()); - - AuthorizationRequest request = new AuthorizationRequest(); - - request.setTicket(extractTicket(testResponse.getHeaders())); - - AuthorizationResponse response = authzClient.authorization("marta", "password").authorize(request); - token = response.getToken(); - - assertNotNull(token); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", "POST", token, headers, parameters, null), - testResponse.clear()); - assertTrue(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("200")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", "POST", token, headers, parameters, null), - testResponse.clear()); - assertFalse(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("50")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", "POST", token, headers, parameters, null), - testResponse.clear()); - assertTrue(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("10")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", "POST", token, headers, parameters, null), - testResponse.clear()); - - request = new AuthorizationRequest(); - - request.setTicket(extractTicket(testResponse.getHeaders())); - - response = authzClient.authorization("marta", "password").authorize(request); - token = response.getToken(); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", "POST", token, headers, parameters, null), - testResponse.clear()); - assertTrue(context.isGranted()); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", "GET", token, headers, parameters, null), - testResponse.clear()); - assertTrue(context.isGranted()); - - assertEquals(1, context.getPermissions().size()); - Permission permission = context.getPermissions().get(0); - - assertEquals(parameters.get("withdrawal.amount").get(0), permission.getClaims().get("withdrawal.amount").iterator().next()); - } - - @Test - public void testEnforceEntitlementAccessWithClaimsWithoutBearerToken() { - initAuthorizationSettings(getClientResource("resource-server-test")); - - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-entitlement-claims-test.json", false); - HashMap> headers = new HashMap<>(); - HashMap> parameters = new HashMap<>(); - - AuthzClient authzClient = policyEnforcer.getAuthzClient(); - String token = authzClient.obtainAccessToken("marta", "password").getToken(); - - AuthzTestUtils.TestResponse testResponse = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse); - assertFalse(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("50")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - assertTrue(context.isGranted()); - assertEquals(1, context.getPermissions().size()); - Permission permission = context.getPermissions().get(0); - assertEquals(parameters.get("withdrawal.amount").get(0), permission.getClaims().get("withdrawal.amount").iterator().next()); - - parameters.put("withdrawal.amount", Arrays.asList("200")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - assertFalse(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("50")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - assertTrue(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("10")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - - assertTrue(context.isGranted()); - - assertEquals(1, context.getPermissions().size()); - permission = context.getPermissions().get(0); - assertEquals(parameters.get("withdrawal.amount").get(0), permission.getClaims().get("withdrawal.amount").iterator().next()); - } - - @Test - public void testEnforceEntitlementAccessWithClaimsWithBearerToken() { - initAuthorizationSettings(getClientResource("resource-server-test")); - - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-entitlement-claims-test.json", false); - HashMap> headers = new HashMap<>(); - HashMap> parameters = new HashMap<>(); - - AuthzClient authzClient = policyEnforcer.getAuthzClient(); - String token = authzClient.obtainAccessToken("marta", "password").getToken(); - - headers.put("Authorization", Arrays.asList("Bearer " + token)); - - AuthzTestUtils.TestResponse testResponse = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse); - assertFalse(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("50")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - assertTrue(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("200")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - assertFalse(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("50")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - assertTrue(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("10")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - - assertTrue(context.isGranted()); - } - - @Test - public void testEnforceEntitlementAccessWithClaimsWithBearerTokenFromPublicClient() { - initAuthorizationSettings(getClientResource("resource-server-test")); - - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-entitlement-claims-test.json", false); - HashMap> headers = new HashMap<>(); - HashMap> parameters = new HashMap<>(); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - String token = response.getAccessToken(); - - headers.put("Authorization", Arrays.asList("Bearer " + token)); - - AuthzTestUtils.TestResponse testResponse = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse); - assertFalse(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("50")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - assertTrue(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("200")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - assertFalse(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("50")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - assertTrue(context.isGranted()); - - parameters.put("withdrawal.amount", Arrays.asList("10")); - - context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/bank/account/1/withdrawal", null, token, headers, parameters, null), - testResponse.clear()); - - assertTrue(context.isGranted()); - } - - private String extractTicket(Map> headers) { - List wwwAuthenticateHeader = headers.get("WWW-Authenticate"); - - assertNotNull(wwwAuthenticateHeader); - assertFalse(wwwAuthenticateHeader.isEmpty()); - - String wwwAuthenticate = wwwAuthenticateHeader.get(0); - return wwwAuthenticate.substring(wwwAuthenticate.indexOf("ticket=") + "ticket=\"".length(), wwwAuthenticate.lastIndexOf('"')); - } - - private void initAuthorizationSettings(ClientResource clientResource) { - if (clientResource.authorization().resources().findByName("Bank Account").isEmpty()) { - JSPolicyRepresentation policy = new JSPolicyRepresentation(); - - policy.setName("Withdrawal Limit Policy"); - policy.setType("script-scripts/enforce-withdraw-limit-policy.js"); - - clientResource.authorization().policies().js().create(policy).close(); - - createResource(clientResource, "Bank Account", "/api/bank/account/{id}/withdrawal", "withdrawal"); - - ScopePermissionRepresentation permission = new ScopePermissionRepresentation(); - - permission.setName("Withdrawal Permission"); - permission.addScope("withdrawal"); - permission.addPolicy(policy.getName()); - - clientResource.authorization().permissions().scope().create(permission).close(); - } - } - - private ResourceRepresentation createResource(ClientResource clientResource, String name, String uri, String... scopes) { - ResourceRepresentation representation = new ResourceRepresentation(); - - representation.setName(name); - representation.setUri(uri); - representation.setScopes(Arrays.asList(scopes).stream().map(ScopeRepresentation::new).collect(Collectors.toSet())); - - try (jakarta.ws.rs.core.Response response = clientResource.authorization().resources().create(representation)) { - - representation.setId(response.readEntity(ResourceRepresentation.class).getId()); - - return representation; - } - } - - private ClientResource getClientResource(String name) { - ClientsResource clients = realmsResouce().realm(REALM_NAME).clients(); - ClientRepresentation representation = clients.findByClientId(name).get(0); - return clients.get(representation.getId()); - } -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/PolicyEnforcerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/PolicyEnforcerTest.java deleted file mode 100644 index 02f16f9e40..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/admin/PolicyEnforcerTest.java +++ /dev/null @@ -1,706 +0,0 @@ -/* - * Copyright 2018 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.authz.admin; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.keycloak.common.Profile.Feature.AUTHORIZATION; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.keycloak.AuthorizationContext; -import org.keycloak.OAuth2Constants; -import org.keycloak.adapters.authorization.PolicyEnforcer; -import org.keycloak.admin.client.resource.ClientResource; -import org.keycloak.admin.client.resource.ClientsResource; -import org.keycloak.admin.client.resource.PermissionsResource; -import org.keycloak.admin.client.resource.ResourcesResource; -import org.keycloak.authorization.client.AuthzClient; -import org.keycloak.models.utils.KeycloakModelUtils; -import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; -import org.keycloak.representations.idm.ClientRepresentation; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.representations.idm.authorization.AuthorizationRequest; -import org.keycloak.representations.idm.authorization.AuthorizationResponse; -import org.keycloak.representations.idm.authorization.JSPolicyRepresentation; -import org.keycloak.representations.idm.authorization.Permission; -import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation; -import org.keycloak.representations.idm.authorization.ResourceRepresentation; -import org.keycloak.representations.idm.authorization.RolePolicyRepresentation; -import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation; -import org.keycloak.representations.idm.authorization.ScopeRepresentation; -import org.keycloak.testsuite.AbstractKeycloakTest; -import org.keycloak.testsuite.ProfileAssume; -import org.keycloak.testsuite.util.AuthzTestUtils; -import org.keycloak.testsuite.util.ClientBuilder; -import org.keycloak.testsuite.util.OAuthClient; -import org.keycloak.testsuite.util.RealmBuilder; -import org.keycloak.testsuite.util.RoleBuilder; -import org.keycloak.testsuite.util.RolesBuilder; -import org.keycloak.testsuite.util.UserBuilder; -import org.keycloak.testsuite.util.WaitUtils; - -/** - * @author Pedro Igor - */ -public class PolicyEnforcerTest extends AbstractKeycloakTest { - - private static final String RESOURCE_SERVER_CLIENT_ID = "resource-server-test"; - private static final String REALM_NAME = "authz-test"; - - @BeforeClass - public static void enabled() { - ProfileAssume.assumeFeatureEnabled(AUTHORIZATION); - } - - @Override - public void addTestRealms(List testRealms) { - testRealms.add(RealmBuilder.create().name(REALM_NAME) - .roles(RolesBuilder.create() - .realmRole(RoleBuilder.create().name("uma_authorization").build()) - .realmRole(RoleBuilder.create().name("uma_protection").build()) - .realmRole(RoleBuilder.create().name("user").build()) - ) - .user(UserBuilder.create().username("marta").password("password") - .addRoles("uma_authorization", "uma_protection", "user") - .role("resource-server-test", "uma_protection")) - .user(UserBuilder.create().username("kolo").password("password")) - .client(ClientBuilder.create().clientId("resource-server-uma-test") - .secret("secret") - .authorizationServicesEnabled(true) - .redirectUris("http://localhost/resource-server-uma-test") - .defaultRoles("uma_protection") - .directAccessGrants()) - .client(ClientBuilder.create().clientId("resource-server-test") - .secret("secret") - .authorizationServicesEnabled(true) - .redirectUris("http://localhost/resource-server-test") - .defaultRoles("uma_protection") - .directAccessGrants()) - .client(ClientBuilder.create().clientId("public-client-test") - .publicClient() - .redirectUris("http://localhost:8180/auth/realms/master/app/auth/*", "https://localhost:8543/auth/realms/master/app/auth/*") - .directAccessGrants()) - .build()); - } - - @Before - public void onBefore() { - initAuthorizationSettings(getClientResource(RESOURCE_SERVER_CLIENT_ID)); - } - - @Test - public void testBearerOnlyClientResponse() { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-bearer-only.json", true); - - AuthzTestUtils.TestResponse testResponse = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resourcea"), testResponse); - - assertFalse(context.isGranted()); - assertEquals(403, testResponse.getStatus()); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - String token = response.getAccessToken(); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resourcea", token), testResponse.clear()); - assertTrue(context.isGranted()); - - testResponse = new AuthzTestUtils.TestResponse(); - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resourceb"), testResponse.clear()); - assertFalse(context.isGranted()); - assertEquals(403, testResponse.getStatus()); - } - - @Test - public void testPathConfigurationPrecendenceWhenLazyLoadingPaths() throws IOException { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-paths.json", false); - - AuthzTestUtils.TestResponse testResponse = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resourcea"), testResponse); - - assertFalse(context.isGranted()); - assertEquals(403, testResponse.getStatus()); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - String token = response.getAccessToken(); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resourcea", token), testResponse.clear()); - assertTrue(context.isGranted()); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/"), testResponse.clear()); - assertTrue(context.isGranted()); - } - - @Test - public void testResolvingClaimsOnce() { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-bearer-only-with-cip.json", true); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - String token = response.getAccessToken(); - - AuthorizationContext context = policyEnforcer.enforce( - AuthzTestUtils.createHttpRequest("/api/resourcea", token, Collections.singletonMap("claim-a", Collections.singletonList("value-claim-a"))), - new AuthzTestUtils.TestResponse()); - Permission permission = context.getPermissions().get(0); - Map> claims = permission.getClaims(); - - assertTrue(context.isGranted()); - assertEquals("value-claim-a", claims.get("claim-a").iterator().next()); - assertEquals("claim-b", claims.get("claim-b").iterator().next()); - } - - @Test - public void testCustomClaimProvider() { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-bearer-only-with-cip.json", true); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - String token = response.getAccessToken(); - - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resourcea", token), new AuthzTestUtils.TestResponse()); - Permission permission = context.getPermissions().get(0); - Map> claims = permission.getClaims(); - - assertTrue(context.isGranted()); - assertEquals("test", claims.get("resolved-claim").iterator().next()); - } - - @Test - public void testOnDenyRedirectTo() { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-on-deny-redirect.json", false); - - AuthzTestUtils.TestResponse response = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resourcea"), response); - - assertFalse(context.isGranted()); - assertEquals(302, response.getStatus()); - List location = response.getHeaders().getOrDefault("Location", Collections.emptyList()); - assertFalse(location.isEmpty()); - assertEquals("/accessDenied", location.get(0)); - } - - @Test - public void testNotAuthenticatedDenyUnmapedPath() { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-bearer-only.json", true); - - AuthzTestUtils.TestResponse response = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/unmmaped"), response); - - assertFalse(context.isGranted()); - assertEquals(403, response.getStatus()); - } - - @Test - public void testMappedPathEnforcementModeDisabled() { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-disabled-enforce-mode-path.json", true); - - AuthzTestUtils.TestResponse response = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource/public"), response); - assertTrue(context.isGranted()); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resourceb"), response.clear()); - assertFalse(context.isGranted()); - assertEquals(403, response.getStatus()); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - String token = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), null).getAccessToken(); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resourcea", token), response.clear()); - assertTrue(context.isGranted()); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resourceb", token), response.clear()); - assertFalse(context.isGranted()); - assertEquals(403, response.getStatus()); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource/public", token), response.clear()); - assertTrue(context.isGranted()); - } - - @Test - public void testDisabledPathNoCache() { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-disabled-path-nocache.json", true); - - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource/public"), new AuthzTestUtils.TestResponse()); - assertTrue(context.isGranted()); - - ClientResource clientResource = getClientResource(RESOURCE_SERVER_CLIENT_ID); - ResourceRepresentation resource = clientResource.authorization().resources() - .findByName("Root").get(0); - - clientResource.authorization().resources().resource(resource.getId()).remove(); - - // first request caches the path and the entry is invalidated due to the lifespan - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource/all-public"), new AuthzTestUtils.TestResponse()); - assertTrue(context.isGranted()); - - WaitUtils.pause(1000); - - // second request can not fail because entry should not be invalidated - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource/all-public"), new AuthzTestUtils.TestResponse()); - assertTrue(context.isGranted()); - } - - @Test - public void testLazyLoadedPathIsCached() { - ClientResource clientResource = getClientResource(RESOURCE_SERVER_CLIENT_ID); - createResource(clientResource, "Static Test Resource", "/api/any-resource/*"); - - ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation(); - - permission.setName("Any Resource Permission"); - permission.addResource("Static Test Resource"); - permission.addPolicy("Always Grant Policy"); - - clientResource.authorization().permissions().resource().create(permission); - - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-disabled-path-nocache.json", true); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - String token = response.getAccessToken(); - - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/any-resource/test", token), new AuthzTestUtils.TestResponse()); - assertTrue(context.isGranted()); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/any-resource/test", token), new AuthzTestUtils.TestResponse()); - assertTrue(context.isGranted()); - - ResourceRepresentation resource = clientResource.authorization().resources() - .findByName("Static Test Resource").get(0); - - clientResource.authorization().resources().resource(resource.getId()).remove(); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/any-resource/test", token), new AuthzTestUtils.TestResponse()); - assertFalse(context.isGranted()); - } - - @Test - public void testEnforcementModeDisabled() { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-disabled-enforce-mode.json", true); - - AuthzTestUtils.TestResponse response = new AuthzTestUtils.TestResponse(); - policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource/public"), response); - assertEquals(401, response.getStatus()); - } - - @Test - public void testMatchHttpVerbsToScopes() { - ClientResource clientResource = getClientResource(RESOURCE_SERVER_CLIENT_ID); - ResourceRepresentation resource = createResource(clientResource, "Resource With HTTP Scopes", "/api/resource-with-scope"); - - ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation(); - - permission.setName(resource.getName() + " Permission"); - permission.addResource(resource.getName()); - permission.addPolicy("Always Grant Policy"); - - PermissionsResource permissions = clientResource.authorization().permissions(); - permissions.resource().create(permission).close(); - - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-match-http-verbs-scopes.json", true); - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - String token = response.getAccessToken(); - - AuthzTestUtils.TestResponse testResponse = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token), testResponse); - - assertFalse("Should fail because resource does not have any scope named GET", context.isGranted()); - assertEquals(403, testResponse.getStatus()); - - resource.addScope("GET", "POST"); - - clientResource.authorization().resources().resource(resource.getId()).update(resource); - - policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-match-http-verbs-scopes.json", true); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token), testResponse.clear()); - assertTrue(context.isGranted()); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token, "POST"), testResponse.clear()); - assertTrue(context.isGranted()); - - // create a PATCH scope without associated it with the resource so that a PATCH request is denied accordingly even though - // the scope exists on the server - clientResource.authorization().scopes().create(new ScopeRepresentation("PATCH")); - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token, "PATCH"), testResponse.clear()); - assertFalse(context.isGranted()); - - ScopePermissionRepresentation postPermission = new ScopePermissionRepresentation(); - - postPermission.setName("GET permission"); - postPermission.addScope("GET"); - postPermission.addPolicy("Always Deny Policy"); - - permissions.scope().create(postPermission).close(); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token), testResponse.clear()); - assertFalse(context.isGranted()); - - postPermission = permissions.scope().findByName(postPermission.getName()); - - postPermission.addScope("GET"); - postPermission.addPolicy("Always Grant Policy"); - - permissions.scope().findById(postPermission.getId()).update(postPermission); - - AuthzClient authzClient = policyEnforcer.getAuthzClient(); - AuthorizationResponse authorize = authzClient.authorization(token).authorize(); - token = authorize.getToken(); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token), testResponse.clear()); - assertTrue(context.isGranted()); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token, "POST"), testResponse.clear()); - assertTrue(context.isGranted()); - - postPermission = permissions.scope().findByName(postPermission.getName()); - postPermission.addScope("GET"); - postPermission.addPolicy("Always Deny Policy"); - permissions.scope().findById(postPermission.getId()).update(postPermission); - authorize = authzClient.authorization(token).authorize(); - token = authorize.getToken(); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token), testResponse.clear()); - assertFalse(context.isGranted()); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token, "POST"), testResponse.clear()); - assertTrue(context.isGranted()); - - postPermission = permissions.scope().findByName(postPermission.getName()); - postPermission.addScope("GET"); - postPermission.addPolicy("Always Grant Policy"); - permissions.scope().findById(postPermission.getId()).update(postPermission); - authorize = authzClient.authorization(token).authorize(); - token = authorize.getToken(); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token), testResponse.clear()); - assertTrue(context.isGranted()); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token, "POST"), testResponse.clear()); - assertTrue(context.isGranted()); - - postPermission = permissions.scope().findByName(postPermission.getName()); - postPermission.addScope("POST"); - postPermission.addPolicy("Always Deny Policy"); - permissions.scope().findById(postPermission.getId()).update(postPermission); - AuthorizationRequest request = new AuthorizationRequest(); - - request.addPermission(null, "GET"); - - authorize = authzClient.authorization(token).authorize(request); - token = authorize.getToken(); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token), testResponse.clear()); - assertTrue(context.isGranted()); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/resource-with-scope", token, "POST"), testResponse.clear()); - assertFalse(context.isGranted()); - } - - @Test - public void testUsingSubjectToken() { - ClientResource clientResource = getClientResource(RESOURCE_SERVER_CLIENT_ID); - ResourceRepresentation resource = createResource(clientResource, "Resource Subject Token", "/api/check-subject-token"); - - ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation(); - - permission.setName(resource.getName() + " Permission"); - permission.addResource(resource.getName()); - permission.addPolicy("Only User Policy"); - - PermissionsResource permissions = clientResource.authorization().permissions(); - permissions.resource().create(permission).close(); - - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-bearer-only.json", true); - AuthzTestUtils.TestResponse testResponse = new AuthzTestUtils.TestResponse(); - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/check-subject-token"), testResponse); - - assertFalse(context.isGranted()); - assertEquals(403, testResponse.getStatus()); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - String token = response.getAccessToken(); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/check-subject-token", token), testResponse.clear()); - assertTrue(context.isGranted()); - } - - @Test - public void testUsingInvalidToken() { - ClientResource clientResource = getClientResource(RESOURCE_SERVER_CLIENT_ID); - ResourceRepresentation resource = createResource(clientResource, "Resource Subject Invalid Token", "/api/check-subject-token"); - - ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation(); - - permission.setName(resource.getName() + " Permission"); - permission.addResource(resource.getName()); - permission.addPolicy("Only User Policy"); - - PermissionsResource permissions = clientResource.authorization().permissions(); - permissions.resource().create(permission).close(); - - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-bearer-only.json", true); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - String token = response.getAccessToken(); - - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/check-subject-token", token), new AuthzTestUtils.TestResponse()); - assertTrue(context.isGranted()); - - oauth.doLogout(response.getRefreshToken(), null); - - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/check-subject-token", token), new AuthzTestUtils.TestResponse()); - assertFalse(context.isGranted()); - } - - @Test - public void testLazyLoadPaths() { - ClientResource clientResource = getClientResource(RESOURCE_SERVER_CLIENT_ID); - - for (int i = 0; i < 200; i++) { - ResourceRepresentation representation = new ResourceRepresentation(); - - representation.setType("test"); - representation.setName("Resource " + i); - representation.setUri("/api/" + i); - - jakarta.ws.rs.core.Response response = clientResource.authorization().resources().create(representation); - - representation.setId(response.readEntity(ResourceRepresentation.class).getId()); - - response.close(); - } - - ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation(); - - permission.setName("Test Permission"); - permission.setResourceType("test"); - permission.addPolicy("Only User Policy"); - - PermissionsResource permissions = clientResource.authorization().permissions(); - permissions.resource().create(permission).close(); - - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-no-lazyload.json", true); - - assertEquals(205, policyEnforcer.getPaths().size()); - - policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-lazyload.json", true); - assertEquals(0, policyEnforcer.getPathMatcher().getPathCache().size()); - assertEquals(0, policyEnforcer.getPaths().size()); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - String token = response.getAccessToken(); - - for (int i = 0; i < 101; i++) { - policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/" + i, token), new AuthzTestUtils.TestResponse()); - } - - assertEquals(101, policyEnforcer.getPathMatcher().getPathCache().size()); - - for (int i = 101; i < 200; i++) { - policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/" + i, token), new AuthzTestUtils.TestResponse()); - } - - assertEquals(200, policyEnforcer.getPathMatcher().getPathCache().size()); - assertEquals(0, policyEnforcer.getPaths().size()); - - ResourceRepresentation resource = clientResource.authorization().resources() - .findByName("Root").get(0); - - clientResource.authorization().resources().resource(resource.getId()).remove(); - - policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-lazyload-with-paths.json", true); - - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api/0", token), new AuthzTestUtils.TestResponse()); - - assertTrue(context.isGranted()); - } - - @Test - public void testSetMethodConfigs() { - ClientResource clientResource = getClientResource(RESOURCE_SERVER_CLIENT_ID); - ResourceRepresentation representation = new ResourceRepresentation(); - - representation.setName(KeycloakModelUtils.generateId()); - representation.setUris(Collections.singleton("/api-method/*")); - - ResourcesResource resources = clientResource.authorization().resources(); - jakarta.ws.rs.core.Response response = resources.create(representation); - - representation.setId(response.readEntity(ResourceRepresentation.class).getId()); - - response.close(); - - try { - PolicyEnforcer policyEnforcer = AuthzTestUtils.createPolicyEnforcer("enforcer-paths-use-method-config.json", true); - - oauth.realm(REALM_NAME); - oauth.clientId("public-client-test"); - oauth.doLogin("marta", "password"); - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse tokeResponse = oauth.doAccessTokenRequest(code, null); - String token = tokeResponse.getAccessToken(); - - AuthorizationContext context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api-method/foo", token), new AuthzTestUtils.TestResponse()); - - // GET is disabled in the config - assertTrue(context.isGranted()); - - PolicyEnforcerConfig.PathConfig pathConfig = policyEnforcer.getPaths().get("/api-method/*"); - - assertNotNull(pathConfig); - List methods = pathConfig.getMethods(); - assertEquals(1, methods.size()); - assertTrue(PolicyEnforcerConfig.ScopeEnforcementMode.DISABLED.equals(methods.get(0).getScopesEnforcementMode())); - - // other verbs should be protected - context = policyEnforcer.enforce(AuthzTestUtils.createHttpRequest("/api-method/foo", token, "POST"), new AuthzTestUtils.TestResponse()); - - assertFalse(context.isGranted()); - } finally { - resources.resource(representation.getId()).remove(); - } - } - - private void initAuthorizationSettings(ClientResource clientResource) { - if (clientResource.authorization().resources().findByName("Resource A").isEmpty()) { - JSPolicyRepresentation jsPolicy = new JSPolicyRepresentation(); - - jsPolicy.setName("Always Grant Policy"); - jsPolicy.setType("script-scripts/default-policy.js"); - - clientResource.authorization().policies().js().create(jsPolicy).close(); - - RolePolicyRepresentation rolePolicy = new RolePolicyRepresentation(); - - rolePolicy.setName("Only User Policy"); - rolePolicy.addRole("user"); - - clientResource.authorization().policies().role().create(rolePolicy).close(); - - createResource(clientResource, "Resource A", "/api/resourcea"); - - ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation(); - - permission.setName("Resource A Permission"); - permission.addResource("Resource A"); - permission.addPolicy(jsPolicy.getName()); - - clientResource.authorization().permissions().resource().create(permission).close(); - } - - if (clientResource.authorization().resources().findByName("Resource B").isEmpty()) { - JSPolicyRepresentation policy = new JSPolicyRepresentation(); - - policy.setName("Always Deny Policy"); - policy.setType("script-scripts/always-deny-policy.js"); - - clientResource.authorization().policies().js().create(policy).close(); - - createResource(clientResource, "Resource B", "/api/resourceb"); - - ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation(); - - permission.setName("Resource B Permission"); - permission.addResource("Resource B"); - permission.addPolicy(policy.getName()); - - clientResource.authorization().permissions().resource().create(permission).close(); - } - - if (clientResource.authorization().resources().findByName("Root").isEmpty()) { - createResource(clientResource, "Root", "/*"); - } - } - - private ResourceRepresentation createResource(ClientResource clientResource, String name, String uri, String... scopes) { - ResourceRepresentation representation = new ResourceRepresentation(); - - representation.setName(name); - representation.setUri(uri); - representation.setScopes(Arrays.asList(scopes).stream().map(ScopeRepresentation::new).collect(Collectors.toSet())); - - jakarta.ws.rs.core.Response response = clientResource.authorization().resources().create(representation); - - representation.setId(response.readEntity(ResourceRepresentation.class).getId()); - - response.close(); - - return representation; - } - - private ClientResource getClientResource(String name) { - ClientsResource clients = realmsResouce().realm(REALM_NAME).clients(); - ClientRepresentation representation = clients.findByClientId(name).get(0); - return clients.get(representation.getId()); - } -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/services/org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/services/org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory deleted file mode 100644 index 8782d98a79..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/services/org.keycloak.adapters.authorization.cip.spi.ClaimInformationPointProviderFactory +++ /dev/null @@ -1,18 +0,0 @@ -# -# * Copyright 2018 Red Hat, Inc. and/or its affiliates -# * and other contributors as indicated by the @author tags. -# * -# * Licensed under the Apache License, Version 2.0 (the "License"); -# * you may not use this file except in compliance with the License. -# * You may obtain a copy of the License at -# * -# * http://www.apache.org/licenses/LICENSE-2.0 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# - -org.keycloak.testsuite.authz.admin.MyCustomCIPFactory \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-bearer-only-with-cip.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-bearer-only-with-cip.json deleted file mode 100644 index 777840f89f..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-bearer-only-with-cip.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - }, - "claim-information-point": { - "claims": { - "claim-b": "claim-b" - } - }, - "paths": [ - { - "path": "/api/resourcea", - "claim-information-point": { - "claims": { - "claim-a": "{request.parameter['claim-a']}" - }, - "my-custom-cip": { - "claim-value": "test" - } - } - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-bearer-only.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-bearer-only.json deleted file mode 100644 index 6482606925..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-bearer-only.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - } -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-claims-provider.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-claims-provider.json deleted file mode 100644 index 122bf26b21..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-claims-provider.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "realm": "test-realm-authz", - "auth-server-url": "http://localhost:8180/auth", - "resource": "test-app-authz", - "credentials": { - "secret": "secret" - }, - "paths": [ - { - "path": "/claims-provider", - "methods": [ - { - "method": "POST", - "scopes": [ - "create" - ] - } - ], - "claim-information-point": { - "claims": { - "claim-from-request-parameter": "{request.parameter['a']}", - "claim-from-header": "{request.header['b']}", - "claim-from-cookie": "{request.cookie['c']}", - "claim-from-remoteAddr": "{request.remoteAddr}", - "claim-from-method": "{request.method}", - "claim-from-uri": "{request.uri}", - "claim-from-relativePath": "{request.relativePath}", - "claim-from-secure": "{request.secure}", - "claim-from-json-body-object": "{request.body['/a/b/c']}", - "claim-from-json-body-array": "{request.body['/d/1']}", - "claim-from-json-body-number": "{request.body['/e/number']}", - "claim-from-body": "{request.body}", - "claim-from-static-value": "static value", - "claim-from-multiple-static-value": ["static", "value"], - "param-replace-multiple-placeholder": "Test {keycloak.access_token['/custom_claim/0']} and {request.parameter['a']} " - } - } - }, - { - "path": "/claims-from-body-json-object", - "methods": [ - { - "method": "POST", - "scopes": [ - "create" - ] - } - ], - "claim-information-point": { - "claims": { - "individualRoles": "{request.body['/Individual/individualRoles']}" - } - } - }, - { - "path": "/http-post-claim-provider", - "claim-information-point": { - "http": { - "claims": { - "claim-a": "/a", - "claim-d": "/d", - "claim-d0": "/d/0", - "claim-d-all": ["/d/0", "/d/1"] - }, - "url": "http://localhost:8989/post-claim-information-provider", - "method": "POST", - "headers": { - "Content-Type": "application/x-www-form-urlencoded", - "header-b": ["header-b-value1", "header-b-value2"], - "Authorization": "Bearer {keycloak.access_token}" - }, - "parameters": { - "param-a": ["param-a-value1", "param-a-value2"], - "param-subject": "{keycloak.access_token['/sub']}", - "param-user-name": "{keycloak.access_token['/preferred_username']}", - "param-other-claims": "{keycloak.access_token['/custom_claim']}" - } - } - } - }, - { - "path": "/http-get-claim-provider", - "claim-information-point": { - "http": { - "url": "http://localhost:8989/get-claim-information-provider", - "method": "get", - "headers": { - "Content-Type": "application/x-www-form-urlencoded", - "header-b": ["header-b-value1", "header-b-value2"], - "Authorization": "Bearer {keycloak.access_token}" - }, - "parameters": { - "param-a": ["param-a-value1", "param-a-value2"], - "param-subject": "{keycloak.access_token['/sub']}", - "param-user-name": "{keycloak.access_token['/preferred_username']}" - } - } - } - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-path-cip.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-path-cip.json deleted file mode 100644 index a757ace7e4..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-path-cip.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "realm": "test-realm-authz", - "auth-server-url": "http://localhost:8180/auth", - "resource": "test-app-authz", - "credentials": { - "secret": "secret" - }, - "paths": [ - { - "path": "/v1/product/*", - "methods": [ - { - "method": "POST", - "scopes": [ - "create" - ] - } - ], - "claim-information-point": { - "claims": { - "claim-a": "{request.parameter['a']}", - "claim-b": "{request.header['b']}", - "claim-c": "{request.cookie['c']}" - } - } - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json deleted file mode 100644 index 7cccc8a87b..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "realm": "test-realm-authz", - "auth-server-url": "http://localhost:8180/auth", - "resource": "test-app-authz", - "credentials": { - "secret": "secret" - }, - "paths": [ - { - "path": "/v1/product/*", - "methods": [ - { - "method": "POST", - "scopes": [ - "create" - ] - } - ] - }, - { - "path": "/v1/product/*", - "methods": [ - { - "method": "GET", - "scopes": [ - "view" - ] - } - ] - }, - { - "path": "/v1/product/*", - "methods": [ - { - "method": "PUT", - "scopes": [ - "update" - ] - } - ] - }, - { - "path": "/v1/product/*", - "methods": [ - { - "method": "DELETE", - "scopes": [ - "delete" - ] - } - ] - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-enforce-mode-path.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-enforce-mode-path.json deleted file mode 100644 index 93793d73a1..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-enforce-mode-path.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - }, - "paths": [ - { - "name": "Resource B", - "path": "/api/resource/public", - "enforcement-mode": "DISABLED" - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-enforce-mode.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-enforce-mode.json deleted file mode 100644 index 87f21c1963..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-enforce-mode.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - }, - "enforcement-mode": "DISABLED", - "paths": [ - { - "name": "Resource B", - "path": "/api/resource/public" - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-path-nocache.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-path-nocache.json deleted file mode 100644 index 2629d853ab..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-disabled-path-nocache.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - }, - "path-cache": { - "lifespan": 1 - }, - "paths": [ - { - "name": "Resource B", - "path": "/api/resource/public", - "enforcement-mode": "DISABLED" - }, - { - "name": "Nonexistent", - "path": "/api/resource/all-public/*", - "enforcement-mode": "DISABLED" - }, - { - "name": "Static Test Resource", - "path": "/api/any-resource/test" - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-entitlement-claims-test.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-entitlement-claims-test.json deleted file mode 100644 index efbdba00d5..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-entitlement-claims-test.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - }, - "paths": [ - { - "path": "/api/bank/account/{id}/withdrawal", - "methods": [ - { - "method": "POST", - "scopes": [ - "withdrawal" - ] - } - ], - "claim-information-point": { - "claims": { - "withdrawal.amount": "{request.parameter['withdrawal.amount']}" - } - } - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-lazyload-with-paths.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-lazyload-with-paths.json deleted file mode 100644 index de2e3f6842..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-lazyload-with-paths.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - }, - "lazy-load-paths": true, - "paths": [ - { - "path": "/disabled", - "enforcement-mode": "DISABLED" - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-lazyload.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-lazyload.json deleted file mode 100644 index 9de3180bcc..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-lazyload.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - }, - "lazy-load-paths": true -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-match-http-verbs-scopes.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-match-http-verbs-scopes.json deleted file mode 100644 index 6d67d75452..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-match-http-verbs-scopes.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - }, - "http-method-as-scope": true -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-no-lazyload.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-no-lazyload.json deleted file mode 100644 index 6482606925..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-no-lazyload.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - } -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-on-deny-redirect.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-on-deny-redirect.json deleted file mode 100644 index 54d3746b5a..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-on-deny-redirect.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - }, - "on-deny-redirect-to": "/accessDenied" -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-paths-use-method-config.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-paths-use-method-config.json deleted file mode 100644 index 0038f44ac5..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-paths-use-method-config.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-test", - "credentials": { - "secret": "secret" - }, - "lazy-load-paths": true, - "paths": [ - { - "path": "/api-method/*", - "methods": [ - { - "method": "GET", - "scopes": [ - "withdrawal" - ], - "scopes-enforcement-mode": "DISABLED" - } - ] - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-paths.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-paths.json deleted file mode 100644 index 50e81da9b7..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-paths.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "realm": "authz-test", - "resource": "resource-server-test", - "auth-server-url": "http://localhost:8180/auth", - "credentials": { - "secret": "secret" - }, - "lazy-load-paths": true, - "paths": [ - { - "name": "Root", - "path": "/*", - "enforcement-mode": "DISABLED" - }, - { - "name": "Resource A", - "path": "/api/*" - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-uma-claims-test.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-uma-claims-test.json deleted file mode 100644 index c858956b8c..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-uma-claims-test.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "realm": "authz-test", - "auth-server-url": "http://localhost:8180/auth", - "resource": "resource-server-uma-test", - "credentials": { - "secret": "secret" - }, - "user-managed-access": {}, - "paths": [ - { - "path": "/api/bank/account/{id}/withdrawal", - "methods": [ - { - "method": "POST", - "scopes": [ - "withdrawal" - ] - } - ], - "claim-information-point": { - "claims": { - "withdrawal.amount": "{request.parameter['withdrawal.amount']}" - } - } - } - ] -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json deleted file mode 100644 index f19f3262f6..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "test-realm-authz", - "realm": "test-realm-authz", - "enabled": true, - "sslRequired": "external", - "requiredCredentials": [ "password" ], - "users": [ - { - "username": "service-account-test-app-authz", - "enabled": true, - "serviceAccountClientId": "test-app-authz", - "clientRoles": { - "test-app-authz" : ["uma_protection"] - } - } - ], - "clients": [ - { - "clientId": "test-app-authz", - "enabled": true, - "baseUrl": "/test-app-authz", - "adminUrl": "/test-app-authz", - "bearerOnly": false, - "authorizationSettings": { - "allowRemoteResourceManagement": true, - "policyEnforcementMode": "ENFORCING", - "resources": [ - { - "name": "Product Resource", - "uri": "/v1/product/*", - "scopes": [ - { - "name": "view", - "name": "create", - "name": "delete", - "name": "update" - } - ] - } - ] - }, - "redirectUris": [ - "/test-app-authz/*" - ], - "secret": "secret" - } - ] -} diff --git a/testsuite/integration-arquillian/util/pom.xml b/testsuite/integration-arquillian/util/pom.xml index bbd389bf96..9ac8045694 100644 --- a/testsuite/integration-arquillian/util/pom.xml +++ b/testsuite/integration-arquillian/util/pom.xml @@ -95,9 +95,5 @@ org.keycloak keycloak-adapter-spi - - org.keycloak - keycloak-policy-enforcer-tests -