keycloak-aplcache

adding cors-exposed-headers to conf add missing field in

1/13/2017 3:28:45 PM

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 472afb7..7f86ba1 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
@@ -101,6 +101,7 @@ public class AuthenticatedActionsHandler {
         if (!deployment.isCors()) return false;
         KeycloakSecurityContext securityContext = facade.getSecurityContext();
         String origin = facade.getRequest().getHeader(CorsHeaders.ORIGIN);
+        String exposeHeaders = deployment.getCorsExposedHeaders();
         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)) {
@@ -124,6 +125,9 @@ public class AuthenticatedActionsHandler {
             facade.getResponse().setStatus(200);
             facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
             facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
+            if (exposeHeaders != null) {
+                facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, exposeHeaders);
+            }
         } else {
             log.debugv("cors validation not needed as we're not a secure session or origin header was null: {0}", facade.getRequest().getURI());
         }
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/CorsHeaders.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/CorsHeaders.java
index 715af3d..416c392 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/CorsHeaders.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/CorsHeaders.java
@@ -30,4 +30,5 @@ public interface CorsHeaders {
     String ORIGIN = "Origin";
     String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
     String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
+    String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
 }
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
index ba7bc5d..31f842c 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
@@ -73,6 +73,7 @@ public class KeycloakDeployment {
     protected int corsMaxAge = -1;
     protected String corsAllowedHeaders;
     protected String corsAllowedMethods;
+    protected String corsExposedHeaders;
     protected boolean exposeToken;
     protected boolean alwaysRefreshToken;
     protected boolean registerNodeAtStartup;
@@ -325,6 +326,14 @@ public class KeycloakDeployment {
         this.corsAllowedMethods = corsAllowedMethods;
     }
 
+    public String getCorsExposedHeaders() {
+        return corsExposedHeaders;
+    }
+
+    public void setCorsExposedHeaders(String corsExposedHeaders) {
+        this.corsExposedHeaders = corsExposedHeaders;
+    }
+
     public boolean isExposeToken() {
         return exposeToken;
     }
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
index 2fd9276..a651753 100755
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
@@ -96,6 +96,7 @@ public class KeycloakDeploymentBuilder {
             deployment.setCorsMaxAge(adapterConfig.getCorsMaxAge());
             deployment.setCorsAllowedHeaders(adapterConfig.getCorsAllowedHeaders());
             deployment.setCorsAllowedMethods(adapterConfig.getCorsAllowedMethods());
+            deployment.setCorsExposedHeaders(adapterConfig.getCorsExposedHeaders());
         }
 
         // https://tools.ietf.org/html/rfc7636
diff --git a/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java b/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java
index 233c1ed..a4f04ec 100644
--- a/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java
+++ b/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java
@@ -53,6 +53,7 @@ public class KeycloakDeploymentBuilderTest {
         assertEquals(1000, deployment.getCorsMaxAge());
         assertEquals("POST, PUT, DELETE, GET", deployment.getCorsAllowedMethods());
         assertEquals("X-Custom, X-Custom2", deployment.getCorsAllowedHeaders());
+        assertEquals("X-Custom3, X-Custom4", deployment.getCorsExposedHeaders());
         assertTrue(deployment.isBearerOnly());
         assertTrue(deployment.isPublicClient());
         assertTrue(deployment.isEnableBasicAuth());
diff --git a/adapters/oidc/adapter-core/src/test/resources/keycloak.json b/adapters/oidc/adapter-core/src/test/resources/keycloak.json
index 9f0a204..f53432f 100644
--- a/adapters/oidc/adapter-core/src/test/resources/keycloak.json
+++ b/adapters/oidc/adapter-core/src/test/resources/keycloak.json
@@ -9,6 +9,7 @@
     "cors-max-age": 1000,
     "cors-allowed-methods": "POST, PUT, DELETE, GET",
     "cors-allowed-headers": "X-Custom, X-Custom2",
+    "cors-exposed-headers": "X-Custom3, X-Custom4",
     "bearer-only": true,
     "public-client": true,
     "enable-basic-auth": true,
diff --git a/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/SharedAttributeDefinitons.java b/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/SharedAttributeDefinitons.java
index e4ff988..a7676ea 100755
--- a/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/SharedAttributeDefinitons.java
+++ b/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/SharedAttributeDefinitons.java
@@ -124,6 +124,12 @@ public class SharedAttributeDefinitons {
             .setAllowExpression(true)
             .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
             .build();
+    protected static final SimpleAttributeDefinition CORS_EXPOSED_HEADERS =
+            new SimpleAttributeDefinitionBuilder("cors-exposed-headers", ModelType.STRING, true)
+            .setXmlName("cors-exposed-headers")
+            .setAllowExpression(true)
+            .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
+            .build();
     protected static final SimpleAttributeDefinition EXPOSE_TOKEN =
             new SimpleAttributeDefinitionBuilder("expose-token", ModelType.BOOLEAN, true)
                     .setXmlName("expose-token")
@@ -191,6 +197,7 @@ public class SharedAttributeDefinitons {
         ATTRIBUTES.add(CORS_MAX_AGE);
         ATTRIBUTES.add(CORS_ALLOWED_HEADERS);
         ATTRIBUTES.add(CORS_ALLOWED_METHODS);
+        ATTRIBUTES.add(CORS_EXPOSED_HEADERS);
         ATTRIBUTES.add(EXPOSE_TOKEN);
         ATTRIBUTES.add(AUTH_SERVER_URL_FOR_BACKEND_REQUESTS);
         ATTRIBUTES.add(ALWAYS_REFRESH_TOKEN);
diff --git a/adapters/oidc/wildfly/wf8-subsystem/src/main/resources/org/keycloak/subsystem/wf8/extension/LocalDescriptions.properties b/adapters/oidc/wildfly/wf8-subsystem/src/main/resources/org/keycloak/subsystem/wf8/extension/LocalDescriptions.properties
index 6244b0c..71101a1 100755
--- a/adapters/oidc/wildfly/wf8-subsystem/src/main/resources/org/keycloak/subsystem/wf8/extension/LocalDescriptions.properties
+++ b/adapters/oidc/wildfly/wf8-subsystem/src/main/resources/org/keycloak/subsystem/wf8/extension/LocalDescriptions.properties
@@ -39,6 +39,7 @@ keycloak.realm.client-key-password=n/a
 keycloak.realm.cors-max-age=CORS max-age header
 keycloak.realm.cors-allowed-headers=CORS allowed headers
 keycloak.realm.cors-allowed-methods=CORS allowed methods
+keycloak.realm.cors-exposed-headers=CORS exposed headers
 keycloak.realm.expose-token=Enable secure URL that exposes access token
 keycloak.realm.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
 keycloak.realm.always-refresh-token=Refresh token on every single web request
@@ -73,6 +74,7 @@ keycloak.secure-deployment.client-key-password=n/a
 keycloak.secure-deployment.cors-max-age=CORS max-age header
 keycloak.secure-deployment.cors-allowed-headers=CORS allowed headers
 keycloak.secure-deployment.cors-allowed-methods=CORS allowed methods
+keycloak.secure-deployment.cors-exposed-headers=CORS exposed headers
 keycloak.secure-deployment.expose-token=Enable secure URL that exposes access token
 keycloak.secure-deployment.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
 keycloak.secure-deployment.always-refresh-token=Refresh token on every single web request
diff --git a/adapters/oidc/wildfly/wf8-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd b/adapters/oidc/wildfly/wf8-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd
index e9839bc..cc51ec4 100755
--- a/adapters/oidc/wildfly/wf8-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd
+++ b/adapters/oidc/wildfly/wf8-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd
@@ -58,6 +58,7 @@
             <xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
             <xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
             <xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="realm-public-key" type="xs:string" minOccurs="1" maxOccurs="1"/>
             <xs:element name="auth-server-url-for-backend-requests" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="always-refresh-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
@@ -88,6 +89,7 @@
             <xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1" />
             <xs:element name="cors-allowed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="resource" type="xs:string" minOccurs="0" maxOccurs="1" />
             <xs:element name="truststore" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="truststore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SharedAttributeDefinitons.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SharedAttributeDefinitons.java
index 02d14e5..fafed42 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SharedAttributeDefinitons.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SharedAttributeDefinitons.java
@@ -124,6 +124,12 @@ public class SharedAttributeDefinitons {
             .setAllowExpression(true)
             .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
             .build();
+    protected static final SimpleAttributeDefinition CORS_EXPOSED_HEADERS =
+            new SimpleAttributeDefinitionBuilder("cors-exposed-headers", ModelType.STRING, true)
+            .setXmlName("cors-exposed-headers")
+            .setAllowExpression(true)
+            .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
+            .build();
     protected static final SimpleAttributeDefinition EXPOSE_TOKEN =
             new SimpleAttributeDefinitionBuilder("expose-token", ModelType.BOOLEAN, true)
                     .setXmlName("expose-token")
@@ -175,6 +181,8 @@ public class SharedAttributeDefinitons {
 
 
 
+
+
     protected static final List<SimpleAttributeDefinition> ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
     static {
         ATTRIBUTES.add(REALM_PUBLIC_KEY);
@@ -192,6 +200,7 @@ public class SharedAttributeDefinitons {
         ATTRIBUTES.add(CORS_MAX_AGE);
         ATTRIBUTES.add(CORS_ALLOWED_HEADERS);
         ATTRIBUTES.add(CORS_ALLOWED_METHODS);
+        ATTRIBUTES.add(CORS_EXPOSED_HEADERS);
         ATTRIBUTES.add(EXPOSE_TOKEN);
         ATTRIBUTES.add(AUTH_SERVER_URL_FOR_BACKEND_REQUESTS);
         ATTRIBUTES.add(ALWAYS_REFRESH_TOKEN);
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/extension/LocalDescriptions.properties b/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/extension/LocalDescriptions.properties
index c0ca52e..a297c1d 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/extension/LocalDescriptions.properties
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/extension/LocalDescriptions.properties
@@ -39,6 +39,7 @@ keycloak.realm.client-key-password=n/a
 keycloak.realm.cors-max-age=CORS max-age header
 keycloak.realm.cors-allowed-headers=CORS allowed headers
 keycloak.realm.cors-allowed-methods=CORS allowed methods
+keycloak.realm.cors-exposed-headers=CORS exposed headers
 keycloak.realm.expose-token=Enable secure URL that exposes access token
 keycloak.realm.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
 keycloak.realm.always-refresh-token=Refresh token on every single web request
@@ -74,6 +75,7 @@ keycloak.secure-deployment.client-key-password=n/a
 keycloak.secure-deployment.cors-max-age=CORS max-age header
 keycloak.secure-deployment.cors-allowed-headers=CORS allowed headers
 keycloak.secure-deployment.cors-allowed-methods=CORS allowed methods
+keycloak.secure-deployment.cors-exposed-headers=CORS exposed headers
 keycloak.secure-deployment.expose-token=Enable secure URL that exposes access token
 keycloak.secure-deployment.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
 keycloak.secure-deployment.always-refresh-token=Refresh token on every single web request
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd b/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd
index 84399a3..8118209 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd
@@ -58,6 +58,7 @@
             <xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
             <xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
             <xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="realm-public-key" type="xs:string" minOccurs="1" maxOccurs="1"/>
             <xs:element name="auth-server-url-for-backend-requests" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="always-refresh-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
@@ -88,6 +89,7 @@
             <xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="bearer-only" type="xs:boolean" minOccurs="0" maxOccurs="1" />
             <xs:element name="cors-allowed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="resource" type="xs:string" minOccurs="0" maxOccurs="1" />
             <xs:element name="truststore" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <xs:element name="truststore-password" type="xs:string" minOccurs="0" maxOccurs="1"/>
diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
index f063962..ddd525b 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
@@ -29,7 +29,7 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 @JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required",
         "resource", "public-client", "credentials",
         "use-resource-role-mappings",
-        "enable-cors", "cors-max-age", "cors-allowed-methods",
+        "enable-cors", "cors-max-age", "cors-allowed-methods", "cors-exposed-headers",
         "expose-token", "bearer-only", "autodetect-bearer-only",
         "connection-pool-size",
         "allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password",
diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java
index dfe4ae6..4a2b7e2 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java
@@ -33,7 +33,7 @@ import java.util.TreeMap;
 @JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required",
         "resource", "public-client", "credentials",
         "use-resource-role-mappings",
-        "enable-cors", "cors-max-age", "cors-allowed-methods",
+        "enable-cors", "cors-max-age", "cors-allowed-methods", "cors-exposed-headers",
         "expose-token", "bearer-only", "autodetect-bearer-only", "enable-basic-auth"})
 public class BaseAdapterConfig extends BaseRealmConfig {
     @JsonProperty("resource")
@@ -48,6 +48,8 @@ public class BaseAdapterConfig extends BaseRealmConfig {
     protected String corsAllowedHeaders;
     @JsonProperty("cors-allowed-methods")
     protected String corsAllowedMethods;
+    @JsonProperty("cors-exposed-headers")
+    protected String corsExposedHeaders;
     @JsonProperty("expose-token")
     protected boolean exposeToken;
     @JsonProperty("bearer-only")
@@ -110,6 +112,14 @@ public class BaseAdapterConfig extends BaseRealmConfig {
          this.corsAllowedMethods = corsAllowedMethods;
      }
 
+    public String getCorsExposedHeaders() {
+        return corsExposedHeaders;
+    }
+
+    public void setCorsExposedHeaders(String corsExposedHeaders) {
+        this.corsExposedHeaders = corsExposedHeaders;
+    }
+
     public boolean isExposeToken() {
          return exposeToken;
      }