keycloak-memoizeit

Details

diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java
index 7f86ba1..a0d60a1 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java
@@ -102,6 +102,14 @@ public class AuthenticatedActionsHandler {
         KeycloakSecurityContext securityContext = facade.getSecurityContext();
         String origin = facade.getRequest().getHeader(CorsHeaders.ORIGIN);
         String exposeHeaders = deployment.getCorsExposedHeaders();
+
+        if (deployment.getPolicyEnforcer() != null) {
+            if (exposeHeaders != null) {
+                exposeHeaders += ",";
+            }
+            exposeHeaders += "WWW-Authenticate";
+        }
+
         String requestOrigin = UriUtils.getOrigin(facade.getRequest().getURI());
         log.debugv("Origin: {0} uri: {1}", origin, facade.getRequest().getURI());
         if (securityContext != null && origin != null && !origin.equals(requestOrigin)) {
diff --git a/testsuite/integration-arquillian/test-apps/cors/cors-realm.json b/testsuite/integration-arquillian/test-apps/cors/cors-realm.json
index e3f0ff2..6525dde 100755
--- a/testsuite/integration-arquillian/test-apps/cors/cors-realm.json
+++ b/testsuite/integration-arquillian/test-apps/cors/cors-realm.json
@@ -26,6 +26,14 @@
             "clientRoles": {
                 "realm-management": [ "realm-admin" ]
             }
+        },
+        {
+            "username": "service-account-cors-database-service",
+            "enabled": true,
+            "serviceAccountClientId": "cors-database-service",
+            "clientRoles": {
+                "cors-database-service" : ["uma_protection"]
+            }
         }
     ],
     "roles" : {
@@ -54,6 +62,49 @@
             "webOrigins": [
                 "http://localhost:8080"
             ]
+        },
+        {
+            "clientId": "cors-database-service",
+            "secret" : "secret",
+            "enabled": true,
+            "baseUrl": "http://localhost:8080/cors-database/products",
+            "redirectUris": [
+                "http://localhost:8080/cors-database/*"
+            ],
+            "webOrigins": [
+                "http://localhost:8080"
+            ],
+            "authorizationServicesEnabled" : true,
+            "authorizationSettings" : {
+                "allowRemoteResourceManagement" : false,
+                "policyEnforcementMode" : "ENFORCING",
+                "resources" : [ {
+                    "name" : "Default Resource",
+                    "uri" : "/*",
+                    "type" : "default"
+                } ],
+                "policies" : [ {
+                    "name" : "Default Policy",
+                    "description" : "A policy that grants access only for users within this realm",
+                    "type" : "js",
+                    "logic" : "POSITIVE",
+                    "decisionStrategy" : "AFFIRMATIVE",
+                    "config" : {
+                        "code" : "// by default, grants any permission associated with this policy\n$evaluation.grant();\n"
+                    }
+                }, {
+                    "name" : "Default Permission",
+                    "description" : "A permission that applies to the default resource type",
+                    "type" : "resource",
+                    "logic" : "POSITIVE",
+                    "decisionStrategy" : "UNANIMOUS",
+                    "config" : {
+                        "defaultResourceType" : "default",
+                        "applyPolicies" : "[\"Default Policy\"]"
+                    }
+                } ],
+                "scopes" : [ ]
+            }
         }
     ],
     "clientScopeMappings": {
diff --git a/testsuite/integration-arquillian/test-apps/cors/database-service/src/main/java/org/keycloak/example/oauth/ProductService.java b/testsuite/integration-arquillian/test-apps/cors/database-service/src/main/java/org/keycloak/example/oauth/ProductService.java
index 321f1ef..ddc22a0 100755
--- a/testsuite/integration-arquillian/test-apps/cors/database-service/src/main/java/org/keycloak/example/oauth/ProductService.java
+++ b/testsuite/integration-arquillian/test-apps/cors/database-service/src/main/java/org/keycloak/example/oauth/ProductService.java
@@ -47,6 +47,7 @@ public class ProductService {
         rtn.add("ipod");
 
         response.addHeader("X-Custom1", "some-value");
+        response.addHeader("WWW-Authenticate", "some-value");
         return rtn;
     }
 }
diff --git a/testsuite/integration-arquillian/test-apps/cors/database-service/src/main/webapp/WEB-INF/keycloak.json b/testsuite/integration-arquillian/test-apps/cors/database-service/src/main/webapp/WEB-INF/keycloak.json
index 993d69c..214a562 100755
--- a/testsuite/integration-arquillian/test-apps/cors/database-service/src/main/webapp/WEB-INF/keycloak.json
+++ b/testsuite/integration-arquillian/test-apps/cors/database-service/src/main/webapp/WEB-INF/keycloak.json
@@ -6,5 +6,11 @@
   "bearer-only" : true,
   "ssl-required": "external",
   "enable-cors": true,
-  "cors-exposed-headers": "X-Custom1"
+  "cors-exposed-headers": "X-Custom1",
+  "credentials": {
+    "secret": "secret"
+  },
+  "policy-enforcer": {
+    "enforcement-mode": "DISABLED"
+  }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/cors/AbstractCorsExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/cors/AbstractCorsExampleAdapterTest.java
index 03a2b71..255accf 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/cors/AbstractCorsExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/cors/AbstractCorsExampleAdapterTest.java
@@ -17,11 +17,15 @@
 
 package org.keycloak.testsuite.adapter.example.cors;
 
+import org.jboss.arquillian.container.test.api.Deployer;
 import org.jboss.arquillian.container.test.api.Deployment;
 import org.jboss.arquillian.graphene.page.Page;
+import org.jboss.arquillian.test.api.ArquillianResource;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.jetbrains.annotations.Nullable;
+import org.junit.After;
 import org.junit.AfterClass;
+import org.junit.Before;
 import org.junit.Test;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
@@ -53,6 +57,9 @@ public abstract class AbstractCorsExampleAdapterTest extends AbstractExampleAdap
     public static final String AUTH_SERVER_HOST = "localhost-auth";
     private static String hostBackup;
 
+    @ArquillianResource
+    private Deployer deployer;
+
     @Page
     @JavascriptBrowser
     private AngularCorsProductTestApp jsDriverAngularCorsProductPage;
@@ -66,7 +73,7 @@ public abstract class AbstractCorsExampleAdapterTest extends AbstractExampleAdap
         return exampleDeployment(AngularCorsProductTestApp.CLIENT_ID);
     }
 
-    @Deployment(name = CorsDatabaseServiceTestApp.DEPLOYMENT_NAME)
+    @Deployment(name = CorsDatabaseServiceTestApp.DEPLOYMENT_NAME, managed = false)
     private static WebArchive corsDatabaseServiceExample() throws IOException {
         return exampleDeployment(CorsDatabaseServiceTestApp.CLIENT_ID);
     }
@@ -74,7 +81,17 @@ public abstract class AbstractCorsExampleAdapterTest extends AbstractExampleAdap
     @Override
     public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
         testRealms.add(
-                loadRealm(new File(EXAMPLES_HOME_DIR + "/cors/cors-realm.json")));
+                loadRealm(new File(TEST_APPS_HOME_DIR + "/cors/cors-realm.json")));
+    }
+
+    @Before
+    public void onBefore() {
+        deployer.deploy(CorsDatabaseServiceTestApp.DEPLOYMENT_NAME);
+    }
+
+    @After
+    public void onAfter() {
+        deployer.undeploy(CorsDatabaseServiceTestApp.DEPLOYMENT_NAME);
     }
 
     static{
@@ -100,6 +117,7 @@ public abstract class AbstractCorsExampleAdapterTest extends AbstractExampleAdap
         waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("ipad");
         waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("ipod");
         waitUntilElement(jsDriverAngularCorsProductPage.getHeaders()).text().contains("\"x-custom1\":\"some-value\"");
+        waitUntilElement(jsDriverAngularCorsProductPage.getHeaders()).text().contains("\"www-authenticate\":\"some-value\"");
 
         jsDriverAngularCorsProductPage.loadRoles();
         waitUntilElement(jsDriverAngularCorsProductPage.getOutput()).text().contains("user");