Skip to main content

Cross Origin Resource Sharing (CORS) issues with Chrome on POST requests

Cross Origin Resource Sharing aka CORS is a mechanism that allows servers to access resources hosted on different domains (servers) through web browsers. Due to security restrictions of early web, browsers restricted cross origin HTTP requests initiated from within scripts (i.e JavaScript scripts). Using the XMLHttpRequest object you could only make HTTP requests to originating domains.

You can now use CORS to access resources hosted on different domains within scripts. This is handled through setting of new HTTP header values. Server's making requests to access resources on different domains use "Origin" header to set where the request is coming from. Server's receiving such requests usually respond with other header values indicating whether Access Control is allowed. "Access-Control-Allow-Origin" header value is used for such purpose.

Resource owners can use this header value to restrict access control to specific domains or allow access by all domains by setting the value of this header attribute to "*" (Access-Control-Allow-Origin: *).

In one my recent projects I ran into an issue with CORS. We had a basic Java web application that was running in Apache Tomcat server. This application had Apache Tomcat's CORS filter turned on. You can find how to achieve that here. This filter provides configuration attributes that you can use to control CORS header values and how resource access control is achieved. You can specify which origins are allowed to access resources for example using "" filter initialization parameter. This filter is also smart enough to determine if the request is not a cross origin request. If it determines that request is coming from the same domain, it allows request to continue instead of issuing 403 (Access Denied code).

The issue I ran into was that a POST request on the same domain was getting issued a 403 and to make this interesting this was only happening in Chrome. Neither Safari nor Firefox had issues with this call. Looking at the CURL of this POST request and comparing to the one that was generated by Firefox, I was able to see a difference. Chrome was attaching the "Origin" header to the request while Firefox was not. According to specification, Origin header is optional and can be specified with same domain requests which is what Chrome was doing. With the set up of the Apache Tomcat's CORS filter configuration, this was causing an issue and Server was issuing the 403.

Looking at the source code of the Apache Tomcat CORS filter, I was able to determine that this was happening because "Content-Type" header value was missing from the original request. I quickly modified my XMLHttpRequest object call by using the setRequestHeader("Content-type", "application/json"); method. This fixed the issue in Chrome while Chrome was still setting the Origin header.