Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enable CORS for tomcat applications with credentials support

I have a simple GWT application running from IIS on my server. I am trying to test HTTP requests to tomcat running on the same server. However, since both the application servers are running on different ports, my browser (chrome and firefox) treats the requests as a CORS request.

To enable tomcat to accept CORS request, I updated it to Tomcat 7.0.52 and enabled the CORS filter in the global web.xml configuration. I tested this simple setup and it seems to work. Here is the code in GWT:

        String url = "http://bavarians:8080/";
        RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, url);
        box.setText(url);
        try
        {
            rb.sendRequest("", new RequestCallback(){

                @Override
                public void onResponseReceived(Request request, Response response)
                {
                    Window.alert(response.getStatusCode() + response.getStatusText());
                }

                @Override
                public void onError(Request request, Throwable exception)
                {
                    Window.alert("Request failed");

                }});
        }
        catch (RequestException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

Here is the CORS filter associated with it:

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
  <init-param>
    <param-name>cors.allowed.origins</param-name>
    <param-value>http://bavarians</param-value>
  </init-param>
  <init-param>
    <param-name>cors.allowed.methods</param-name>
    <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
  </init-param>
  <init-param>
    <param-name>cors.allowed.headers</param-name>
    <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Authorization</param-value>
  </init-param>
  <init-param>
    <param-name>cors.exposed.headers</param-name>
    <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials, Authorization</param-value>
  </init-param>
  <init-param>
    <param-name>cors.support.credentials</param-name>
    <param-value>true</param-value>
  </init-param>
  <init-param>
    <param-name>cors.preflight.maxage</param-name>
    <param-value>10</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

With this setup, I get a 200 OK response from tomcat. So its safe to assume that CORS filter is working. To back this up, I took a fiddler trace and all looked good. Fiddler trace with the above setup

Now, since I want to access one of the apps of tomcat(solr), I need basic authentication with my CORS request. This brings a preflight request into picture. Since I setup my CORS filter to enable credential use, I didn't need any changes to it. So, I made the following change to my code

        String url = "http://bavarians:8080/solr/select?wt=xml&q=tag_name:abcd&username=domain\\userid";
        RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, url);
        box.setText(url);
        rb.setHeader("Authorization", "Basic YWRtaW46YWRtaW4=");
        rb.setIncludeCredentials(true);

Now, when I try to use this code, it gets inside the onResponseReceived code block and gives an alert box with "0" value. When I took a fiddler trace, I get this:

Fiddler trace with preflight request.

It makes sense for the browser to send a preflight request since I am adding the custom header to the request. But I don't understand why tomcat responds with a 401 code despite adding the authorization header to its CORS filter configuration.

I'd appreciate any help or response


EDIT: One more thing that I have noticed- if my URL is just "bavarians:8080/solr/";, tomcat successfully authorizes the preflighted request and the immediate next request is processed as a normal GET request with a 200 OK response. But if I enter the function name and query with the URL, I get 401 again. Accessing the above URL from browser requires Basic Authentication. So CORSFilter does work until some point

like image 432
haunteddevil619 Avatar asked Oct 02 '22 04:10

haunteddevil619


1 Answers

Credentials won't be sent in the preflight request, so you have to configure Tomcat to let the request reach the CorsFilter even when unauthenticated. That is, you have to declare a <security-constraint> with <http-method>OPTIONS</http-method> and no <auth-constraint>.

like image 150
Thomas Broyer Avatar answered Oct 05 '22 11:10

Thomas Broyer