CORS : Simple vs Preflight request

Pradeep kumar R
4 min readAug 11, 2018

--

Narrative

CORS, preflight requests in a nutshell, There are active topics in stack overflow about CORS and the preflight request and the reasons why it is needed. I am collating the key aspects of the same concept’s implications and repercussions drawn out of this scenario.

What is CORS?

In order to relax the same origin policy CORS helps modern browsers to achieve cross domain resource access. CORS (Cross Origin Resource Sharing) is a simple mechanism to let a web app running at one origin to access resources securely at another origin with permissions(via headers if applicable). This permission is more of a mechanism with headers for security reasons standard, as browsers restrict cross-origin HTTP requests initiated from within scripts to help mitigate the risk. I am not going to dwell around CORS as there are enough articles to refer to, lets evaluate actual reason for preflight request.

Why Preflight request?

As per the W3C specification(For HTTP request methods in particular, other than GET or POST with certain content types), browsers first makes the preflight (OPTIONS request ) in order to validate whether the supported methods are valid from the server. When the browser get a valid response from the server, then it makes the request with the actual HTTP request method. Servers can also notify clients that cookies and HTTP Authentication is mandatory & should be sent with requests as it depends on the end point configuration. Also the server should validate the Origin header to ensure that it is allowed to make the cross origin request.

We cannot force browsers avoid the options request in case of non simple requests type.

How can we avoid Preflight request?

Simple request

This is clear from CORS specification that preflight request is not mandatory in case of Simple requests ( if all of the following conditions are met )

If the method is

GET/HEAD/POST

If we manually set headers like

Accept, Accept Language, Content-Language, Content-Type(refer below for more conditions )

If we set only the following Content Type

application/x-www-form-urlencoded or multipart/form-data or text/plain

The above specifies the major conditions for a simple request, For more details please refer to the CORS articles or w3c CORS specification.

Final Inference

  1. If we are not doing the simple request, then its obvious to enable OPTIONS http request on the server side to enable a successful preflight request by any browser.
  2. If you already have a simple HTTP request like GET or POST but you intend to specify the content types other than above then please enable the CORS with OPTIONS preflight request else the API request fails.
  3. If any of the API needs token for authorization, then it is advisable to set it in Authorization header for sending Bearer or Basic access token, in such a scenario for preflight request we could do one of the following

if POST, we can enable OPTIONS for preflight as the client needs to send the Authorization Header in the request

if GET, we can set CORS to allow additional header (Authorization) and can avoid OPTIONS preflight. ( could be applicable for POST )

P.S.

1. the above settings could be set at API Gateway level (recommended) or at the direct service/server level.

2. In API gateway, Value for the Access-Control-Allow-Headers header, expects a comma delimited string (e.g. Origin, Authorization) instead of * which could be vulnerable for CSRF

Caching Preflight

In addition to above settings, we can even cache preflight request so that until the cache expires preflight request could be avoided.

  1. API gateway (Most of the plugins/policies )

max_age Indicating how long the results of the preflight request can be cached, in seconds.

2. Header config on server side

The Access-Control-Max-Age response header could be set to a value in seconds which specifies the caching time for preflight request (that is the information contained in the Access-Control-Allow-Methods and Access-Control-Allow-Headers headers) can be cached.

Please refer to the articles below for more details & Follow on LinkedIn

Image Reference

image source : Mozilla

Other References

<style>
.libutton {
display: flex;
flex-direction: column;
justify-content: center;
padding: 7px;
text-align: center;
outline: none;
text-decoration: none !important;
color: #ffffff !important;
width: 200px;
height: 32px;
border-radius: 16px;
background-color: #0A66C2;
font-family: “SF Pro Text”, Helvetica, sans-serif;
}
</style>
<a class=”libutton” href=”https://www.linkedin.com/comm/mynetwork/discovery-see-all?usecase=PEOPLE_FOLLOWS&followMember=rpradeepkumar” target=”_blank”>Follow on LinkedIn</a>

--

--