The minimum every developer must know about CORS

·

3 min read

What is CORS?

  • CORS stands for Cross-Origin Resource Sharing.
  • CORS is HTTP-header based mechanism set by server to inform client side about allowed origins (<scheme>://<hostname>:<port>) other than its own. It also indicates method and headers which the server is willing to support (example included below).
  • Most of client browsers enforce CORS whenever a cross-origin request is made. A request is cross-origin if it calls to outside origins, which are different from the one served the first resource.

CORS behaviour will be different between simple & “pre-flighted” requests. Let’s see the detail below.

Simple requests

  • Refer here for full definition of simple request. For example, a GET request with no header is a simple request.
  • A simple request is sent directly to server.

    Source: MDN web docs Source: MDN web docs

    • Request 1: Client browser first load a web document from domain-a.com . The main request defines its origin as domain-a.com. This origin is then specified in the request header of subsequent requests.
      Origin: <origin>
      
    • Request 2: Client browser then send request to GET resource from domain-a.com. As comming from the same origin, the requested resource is fetched & rendered by browser.
    • Request 3: similar to request 2, but the request now is sent to domain-b.com , which is a different origin.
      • The resource will be successfully fetched, but ...
      • It might be rendered by the browser only if in the response header, the allowed origin == domain-a.com (the request origin) or when it is a wildcard (*) meaning permit all origin.
        Access-Control-Allow-Origin: <origin> | *
        

“Pre-flighted” requests

  • Any requests that are not simple is “pre-flighted” one.
  • Unlike simple request, the browser will send a “preflight” request (OPTION method) to see if the actual one (”pre-flighted” one) is allowed by the server.

    Source: MDN web docs Source: MDN web docs

  • A preflight request will include the following headers:

    Origin: <origin>
    Access-Control-Request-Method: <method>
    Access-Control-Request-Headers: <field-name>[, <field-name>]*
    
    • To inform server about method and headers used in the actual request.
    • To ask if the server allow client origin with given headers & method.
  • Server responses with the following headers if it supports:
    Access-Control-Allow-Origin: <origin> | *
    Access-Control-Allow-Methods: <method>[, <method>]*
    Access-Control-Allow-Headers: <header-name>[, <header-name>]*
    
    Indicating origin, method & headers the server supports
  • Then, the browser will compare value in the response header against corresponding info of the actual request. If all is allowed, the actual request is sent; otherwise, not.
  • The preflight request can also be cached in client side with the time-to-live indicated in Access-Control-Max-Age response header

Final note

CORS is server-side security configurations that clients may enforce it.

  • Most browsers do (to avoid attack like CSRF).
  • Some dev tools do not (like Postman).

Further reading & references:

This article just covers surface of CORS. Further reading is highly recommended!

Follow me (@vietmle_) on Twitter to get update whenever my new article is out!