Browse Source

CORS: Allowed to configure allow-credentials header to work via SSL

This adds support to return the "Access-Control-Allow-Credentials" header
if needed, so CORS will work flawlessly with authenticated applications.

Closes #6380
Alexander Reelsen 11 years ago
parent
commit
35e67c84fa

+ 4 - 0
docs/reference/modules/http.asciidoc

@@ -57,6 +57,10 @@ be cached for. Defaults to `1728000` (20 days)
 |`http.cors.allow-headers` |Which headers to allow. Defaults to
 `X-Requested-With, Content-Type, Content-Length`.
 
+|`http.cors.allow-credentials` | Whether the `Access-Control-Allow-Credentials`
+header should be returned. Note: This header is only returned, when the setting is
+set to `true`. Defaults to `false`
+
 
 |=======================================================================
 

+ 10 - 5
src/main/java/org/elasticsearch/http/netty/NettyHttpChannel.java

@@ -43,6 +43,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
 
+import static org.elasticsearch.http.netty.NettyHttpServerTransport.*;
 import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
 
 /**
@@ -97,20 +98,24 @@ public class NettyHttpChannel extends HttpChannel {
             resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status);
         }
         if (RestUtils.isBrowser(nettyRequest.headers().get(USER_AGENT))) {
-            if (transport.settings().getAsBoolean("http.cors.enabled", true)) {
+            if (transport.settings().getAsBoolean(SETTING_CORS_ENABLED, true)) {
                 String originHeader = request.header(ORIGIN);
                 if (!Strings.isNullOrEmpty(originHeader)) {
                     if (corsPattern == null) {
-                        resp.headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, transport.settings().get("http.cors.allow-origin", "*"));
+                        resp.headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, transport.settings().get(SETTING_CORS_ALLOW_ORIGIN, "*"));
                     } else {
                         resp.headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, corsPattern.matcher(originHeader).matches() ? originHeader : "null");
                     }
                 }
                 if (nettyRequest.getMethod() == HttpMethod.OPTIONS) {
                     // Allow Ajax requests based on the CORS "preflight" request
-                    resp.headers().add(ACCESS_CONTROL_MAX_AGE, transport.settings().getAsInt("http.cors.max-age", 1728000));
-                    resp.headers().add(ACCESS_CONTROL_ALLOW_METHODS, transport.settings().get("http.cors.allow-methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE"));
-                    resp.headers().add(ACCESS_CONTROL_ALLOW_HEADERS, transport.settings().get("http.cors.allow-headers", "X-Requested-With, Content-Type, Content-Length"));
+                    resp.headers().add(ACCESS_CONTROL_MAX_AGE, transport.settings().getAsInt(SETTING_CORS_MAX_AGE, 1728000));
+                    resp.headers().add(ACCESS_CONTROL_ALLOW_METHODS, transport.settings().get(SETTING_CORS_ALLOW_METHODS, "OPTIONS, HEAD, GET, POST, PUT, DELETE"));
+                    resp.headers().add(ACCESS_CONTROL_ALLOW_HEADERS, transport.settings().get(SETTING_CORS_ALLOW_HEADERS, "X-Requested-With, Content-Type, Content-Length"));
+                }
+
+                if (transport.settings().getAsBoolean(SETTING_CORS_ALLOW_CREDENTIALS, false)) {
+                    resp.headers().add(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
                 }
             }
         }

+ 7 - 0
src/main/java/org/elasticsearch/http/netty/NettyHttpServerTransport.java

@@ -65,6 +65,13 @@ public class NettyHttpServerTransport extends AbstractLifecycleComponent<HttpSer
         NettyUtils.setup();
     }
 
+    public static final String SETTING_CORS_ENABLED = "http.cors.enabled";
+    public static final String SETTING_CORS_ALLOW_ORIGIN = "http.cors.allow-origin";
+    public static final String SETTING_CORS_MAX_AGE = "http.cors.max-age";
+    public static final String SETTING_CORS_ALLOW_METHODS = "http.cors.allow-methods";
+    public static final String SETTING_CORS_ALLOW_HEADERS = "http.cors.allow-headers";
+    public static final String SETTING_CORS_ALLOW_CREDENTIALS = "http.cors.allow-credentials";
+
     private final NetworkService networkService;
     final BigArrays bigArrays;
 

+ 2 - 0
src/test/java/org/elasticsearch/rest/CorsRegexDefaultTests.java

@@ -38,6 +38,7 @@ public class CorsRegexDefaultTests extends ElasticsearchIntegrationTest {
         assertThat(response.getStatusCode(), is(200));
         assertThat(response.getHeaders(), hasKey("Access-Control-Allow-Origin"));
         assertThat(response.getHeaders().get("Access-Control-Allow-Origin"), is("*"));
+        assertThat(response.getHeaders(), not(hasKey("Access-Control-Allow-Credentials")));
     }
 
     @Test
@@ -46,5 +47,6 @@ public class CorsRegexDefaultTests extends ElasticsearchIntegrationTest {
 
         assertThat(response.getStatusCode(), is(200));
         assertThat(response.getHeaders(), not(hasKey("Access-Control-Allow-Origin")));
+        assertThat(response.getHeaders(), not(hasKey("Access-Control-Allow-Credentials")));
     }
 }

+ 7 - 2
src/test/java/org/elasticsearch/rest/CorsRegexTests.java

@@ -32,9 +32,12 @@ import org.junit.Test;
 
 import java.net.InetSocketAddress;
 
+import static org.elasticsearch.http.netty.NettyHttpServerTransport.SETTING_CORS_ALLOW_ORIGIN;
+import static org.elasticsearch.http.netty.NettyHttpServerTransport.SETTING_CORS_ALLOW_CREDENTIALS;
 import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
 import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
 import static org.hamcrest.Matchers.*;
+import static org.hamcrest.Matchers.is;
 
 /**
  *
@@ -47,8 +50,8 @@ public class CorsRegexTests extends ElasticsearchIntegrationTest {
     @Override
     protected Settings nodeSettings(int nodeOrdinal) {
         return ImmutableSettings.settingsBuilder()
-                .put("http.cors.allow-origin", "/https?:\\/\\/localhost(:[0-9]+)?/")
-                .put("network.host", "127.0.0.1")
+                .put(SETTING_CORS_ALLOW_ORIGIN, "/https?:\\/\\/localhost(:[0-9]+)?/")
+                .put(SETTING_CORS_ALLOW_CREDENTIALS, "true")
                 .put(super.nodeSettings(nodeOrdinal))
                 .build();
     }
@@ -62,6 +65,8 @@ public class CorsRegexTests extends ElasticsearchIntegrationTest {
         corsValue = "https://localhost:9200";
         response = httpClient().method("GET").path("/").addHeader("User-Agent", "Mozilla Bar").addHeader("Origin", corsValue).execute();
         assertResponseWithOriginheader(response, corsValue);
+        assertThat(response.getHeaders(), hasKey("Access-Control-Allow-Credentials"));
+        assertThat(response.getHeaders().get("Access-Control-Allow-Credentials"), is("true"));
     }
 
     @Test