Dropwizard does not set the 'Access-Control-Allow-Origin' in the response despite CORS being setup

3,628 views
Skip to first unread message

kart...@gmail.com

unread,
Jul 6, 2017, 8:45:17 AM7/6/17
to dropwizard-user
Hi, 

I have setup CORS filter in my dropwizard application as below. But I don't see dropwizard setting the 'Access-Control-Allow-Origin' header in the server response. My browser returns a 401 Authorisation error.
My REST endpoint (http://localhost:8199/api/iceberg/reconciliationsis working fine and returns a valid JSON message when invoked.

Can you please advise how I can resolve this issue or find out why dropwizard is not setting the expected headers?

My CORS setup in dropwizard is as below

@Override
public void run(MyAppConfiguration myAppConfiguration, Environment environment) throws Exception {
    //Force browsers to reload all js and html files for every request as angular gets screwed up
    environment.servlets()
            .addFilter("CacheBustingFilter", new CacheBustingFilter())
            .addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");

    enableCorsHeaders(environment);

}


private void enableCorsHeaders(Environment env) {
        final FilterRegistration.Dynamic cors = env.servlets().addFilter("CORS", CrossOriginFilter.class);

        // Configure CORS parameters
        cors.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
        cors.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin");
        cors.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "OPTIONS,GET,PUT,POST,DELETE,HEAD");

        // Add URL mapping
        cors.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
    }


 When I call the REST endpoint from my angular application I don't see dropwizard returning the 'Access-Control-Allow-Origin' header on the response.  I also don't see any preflight requests from the application.
The HTTP request-response is as below when the http://localhost:8199/api/iceberg/reconciliations is called from my angular application.

GET http://localhost:8199/api/iceberg/reconciliations
Accept: application/json, text/plain, */*
Origin: http://localhost:4200
X-DevTools-Emulate-Network-Conditions-Client-Id: 90d7ac77-f45f-4d60-a667-a56da9e0582b
X-DevTools-Request-Id: 7836.4077
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
Referer: http://localhost:4200/dashboard
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6

HTTP/1.1 401 Unauthorized
Date: Thu, 06 Jul 2017 10:59:14 GMT
WWW-Authenticate: BASIC realm="application"
Content-Length: 0


CURL - OPTIONS METHOD

Moreover I checked using CURL to see  how the OPTIONS method response looks like from the server, I get the same not authorized 401 response.

$ curl -H "Origin: http://example.com"        
-H "Access-Control-Request-Method: POST"        
-H "Access-Control-Request-Headers: X-Requested-With"        
-X OPTIONS --verbose http://localhost:8199/api/iceberg/reconciliations

CURL command response does not have the Access control header

* STATE: INIT => CONNECT handle 0x6000578f0; line 1410 (connection #-5000)
    * Added connection 0. The cache now contains 1 members
    * STATE: CONNECT => WAITRESOLVE handle 0x6000578f0; line 1446 (connection #0)
    *   Trying ::1...
    * TCP_NODELAY set
    * STATE: WAITRESOLVE => WAITCONNECT handle 0x6000578f0; line 1527 (connection #0)
    * Connected to localhost (::1) port 8199 (#0)
    * STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x6000578f0; line 1579 (connection #0)
    * Marked for [keep alive]: HTTP default
    * STATE: SENDPROTOCONNECT => DO handle 0x6000578f0; line 1597 (connection #0)
    > OPTIONS /api/iceberg/reconciliations HTTP/1.1
    > Host: localhost:8199
    > User-Agent: curl/7.54.1
    > Accept: */*
    > Origin: http://example.com
    > Access-Control-Request-Method: POST
    > Access-Control-Request-Headers: X-Requested-With
    >
    * STATE: DO => DO_DONE handle 0x6000578f0; line 1676 (connection #0)
    * STATE: DO_DONE => WAITPERFORM handle 0x6000578f0; line 1801 (connection #0)
    * STATE: WAITPERFORM => PERFORM handle 0x6000578f0; line 1811 (connection #0)
    * HTTP 1.1 or later with persistent connection, pipelining supported
    < HTTP/1.1 401 Unauthorized
    < Date: Thu, 06 Jul 2017 10:53:52 GMT
    < WWW-Authenticate: BASIC realm="application"
    < Content-Length: 0

William Herbert

unread,
Jul 6, 2017, 9:09:40 AM7/6/17
to dropwiz...@googlegroups.com
Try adding:
cors.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");


--
You received this message because you are subscribed to the Google Groups "dropwizard-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dropwizard-user+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
William Herbert
Wm.He...@gmail.com

kart...@gmail.com

unread,
Jul 6, 2017, 9:30:37 AM7/6/17
to dropwizard-user
I also tried setting up the headers as below with explicitly mentioning the domain or passing * in the allow origin header . Both give the same issue response 401 UnAuthorized. 

corsFilter.setInitParameter("Access-Control-Allow-Credentials", "true");
corsFilter.setInitParameter("Access-Control-Allow-Origin", "*");
corsFilter.setInitParameter("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Headers, Access-Control-Request-Method, Cache-Control, Pragma, Expires");
corsFilter.setInitParameter("Access-Control-Allow-Methods\" ", "OPTIONS,GET,PUT,POST,DELETE,HEAD");

Explicitly setting the header
corsFilter.setInitParameter("Access-Control-Allow-Credentials", "true");
corsFilter.setInitParameter("Access-Control-Allow-Origin", "http://localhost:4200");
corsFilter.setInitParameter("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Headers, Access-Control-Request-Method, Cache-Control, Pragma, Expires");
corsFilter.setInitParameter("Access-Control-Allow-Methods\" ", "OPTIONS,GET,PUT,POST,DELETE,HEAD");

Thanks

James Milligan

unread,
Jul 6, 2017, 10:09:25 AM7/6/17
to dropwizard-user
If you give curl the same origin as the server, does it still return a 401? If so, I don't think your problem is your CORS config, but your authentication/authorization and how it's treating OPTIONS requests. Easiest thing to do is add a check in your filter to check the request type, and just return straight away if it's an OPTIONS request (e.g. https://github.com/TheGTC/gtc-api/blob/master/api/src/main/java/uk/org/gtc/api/JWTFilter.java#L46)

If you're not doing any of that stuff, then FWIW I have the following which works as intended (configuration.corsOrigins is set to "https?://*.blah.com,http://localhost")

        // CORS configuration
       
final FilterRegistration.Dynamic corsFilter = environment.servlets().addFilter("CORS", CrossOriginFilter.class);
        corsFilter
.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
        corsFilter
.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM,
               
"Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin");
        corsFilter
.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,PUT,POST,DELETE,OPTIONS");
        corsFilter
.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, configuration.corsOrigins);
        corsFilter
.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");

Karan Kumar

unread,
Oct 23, 2018, 3:18:43 AM10/23/18
to dropwizard-user
Even I was facing a similar issue. 
In my case my front end app was adding a csrf token in the header causing cors to fail. I just had to whitelist the header in the corsFilter.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM() and it worked. Try putting the debugger in the CrossOriginFilter  handle request method and then check.
Reply all
Reply to author
Forward
0 new messages