What is CORS?

CORS, which stands for “Cross-Origin Resource Sharing,” is a security standard that enables servers to indicate the origins from which browsers are allowed to request resources. It was created to refine the same-origin policy (SOP), which browsers use to prevent malicious applications from accessing sensitive data on domains they do not control.

In this article, we’ll start by reviewing the importance of the SOP before discussing how CORS works. We’ll then explore the benefits and best practices for implementing CORS effectively.

What is the same-origin policy?

The same-origin policy (SOP) is a browser security feature that restricts how resources can be accessed by different web applications. This policy requires that a resource must be from the same origin as the web application that is attempting to access it.

For two origins to be considered the same, they must have the same host, scheme, and port. Let’s take this URL for example: https://blog.postman.com:3000. The scheme is HTTPS, the host is blog.postman.com (with blog being a subdomain of postman.com), and the port is 3000. The port number is typically excluded for origins with a domain name, but it is included in our example for reference purposes.

An origin with an “http” scheme is not the same as an otherwise identical origin with an “https” scheme. However, https://blog.postman.com has the same origin as https://blog.postman.com/tag/api-first because they have the same scheme, host, and port.

While the SOP restricts cross-origin access to resources, it is more permissive for certain types of resources, including:

  • Images: Webpages can embed images from any origin without any restrictions.
  • CSS stylesheets: External CSS can be loaded on a webpage by using the link tag directly in the HTML or the @import rule in a different stylesheet file.
  • Scripts: JavaScript files can be loaded and executed from any origin, but they can only access and manipulate DOM elements from the origin in which they are loaded. They are subjected to the SOP restrictions and can’t make cross-origin external API calls.
  • Media files: Audio and video files can be embedded and played from different origins using the <audio> or <video> tags.
  • Iframes: Embedded iframes can load content from any origin, but the SOP isolates the content within an iframe from the parent page’s content. An iframe can communicate with its parent page using an interface exposed by JavaScript, but it does not have direct access to the parent page’s resources because they are not on the same origin.

How does CORS work?

While the same-origin policy, which is strictly implemented on the client side, sets a default restriction on access to some resources, CORS enables the servers that are hosting these resources to specify who they want to give access to. It therefore overrides the restriction that the SOP places on these resources. CORS relies on HTTP request and response headers to communicate with and get permission from the resource server.

CORS requests

There are two primary types of CORS requests: simple requests and preflight requests.

Simple requests are CORS requests that are sent as a part of the main HTTP request. For a simple request to be sent to the server, the following criteria must be met:

  • The request must use the GET, HEAD, or POST HTTP method.
  • The request headers must be simple headers, which are HTTP headers that are safe to be automatically set by user agents. Simple headers include Accept, Accept-Language, Content-Language, and Content-Type.
  • If the request uses the POST method, which indicates that the request has a request body, the Content-Type header must have a value of application/x-www-form-urlencoded, multipart/form-data, or text/plain.

Preflight requests are much more complex than simple requests. They are used when:

  • The original request uses a method other than GET, HEAD, or POST. Typically, these requests use the DELETE and PUT methods.
  • The original request uses content types other than application/x-www-form-urlencoded, multipart/form-data, or text/plain in POST requests.

The browser sends a “preflight request” to the server for any action that mutates data. This is because requests that update data are not considered safe, so the browser first makes sure the server allows CORS before sending the actual request itself.

The preflight request uses the OPTIONS HTTP method to confirm that the server will allow the original request. The browser also includes the following headers with the preflight requests:

  • Access-Control-Request-Method: This header contains the HTTP method that will be used when the browser makes the actual request. It tells the server what to expect when the real request is made.
  • Access-Control-Request-Headers: This is a list of headers that will be sent with the actual request, including custom request headers.

If the preflight request is successful and the browser confirms that the server allows CORS, the actual request will be sent to the server. Otherwise, the browser won’t make the request and will instead receive a CORS error.

CORS response

The server uses response headers to share information about CORS with the browser. The response to a CORS request will typically contain the following headers:

  • Access-Control-Allow-Origin: This header tells the browser which origins can access its resources. It can be set to the value of the origin itself (for example, https://postman.com), or it can use a wildcard (*) instead.
  • Access-Control-Allow-Credentials: This header is a boolean value that indicates whether the browser should include credentials (like cookies or HTTP authentication credentials) when making a cross-origin request. If this header is set to false in the response to a preflight request, the credentials are not included in the actual request. If a simple request is made with this header set to false, the browser will not include this credential in the actual request.
  • Access-Control-Allow-Methods: This header is used in a response to a preflight request to indicate which request methods are allowed in the main request.
  • Access-Control-Allow-Headers: This header is used in a response to a preflight request to indicate which headers are allowed in the main request.
  • Access-Control-Max-Age This header specifies the maximum time (in seconds) for which the response to a preflight request can be cached.
  • Access-Control-Expose-Headers: This header specifies which headers can be exposed to the browser. Any header that is not specified here will not be accessible by client-side JavaScript code.

A successful response to a CORS request can include any HTTP status code as long as it contains one or more of the response headers listed above. However, a successful response to a CORS preflight request must indicate an OK status (i.e., 200 or 204).

What are the benefits of working with CORS?

CORS improves an application’s overall security posture while improving flexibility and interoperability. Its main benefits include:

  • Enhanced API security: CORS helps prevent malicious applications from making unauthorized cross-origin requests to sensitive resources on a different domain. By relaxing the same-origin policy (SOP) and requiring explicit permission through CORS headers, it reduces the risk of cross-site request forgery (CSRF) attacks and unauthorized data access.
  • Cross-origin authentication: CORS enables secure cross-origin authentication by permitting the transmission of credentials (such as cookies or authentication tokens) in cross-origin requests. This is essential for Single Sign-On (SSO) and other authentication mechanisms.
  • Standardization: CORS is a standardized mechanism that is supported by all major web browsers. This uniform implementation across browsers ensures a consistent and reliable approach to handling cross-origin requests.
  • API integration: CORS is essential for integrating web applications with external APIs, enabling developers to utilize third-party functionality in their own services.

What are some best practices for implementing CORS?

While CORS was designed to securely override the same-origin policy, it comes with its own security considerations. Improper implementation of CORS can put your application at risk of data breaches and sensitive data exposure. It is therefore important to follow the recommended industry best practices, such as:

  • Avoid cache poisoning: If the server’s Access-Control-Max-Age header is set to a long duration and the response is cached, outdated permissions may be used for subsequent requests, leading to potential security issues. Ensure that Access-Control-Max-Age is set to a moderate duration (the default and recommended duration is five seconds).
  • Be explicit: It is not recommended to use wildcards (*). Instead, explicitly specify the origins that are allowed to access the server’s resources by using the Access-Control-Allow-Origin header. You should also explicitly specify the allowed methods and headers using Access-Control-Allow-Methods and Access-Control-Allow-Headers. Only use wildcards when you’re very sure you want the API to be accessible from any origin.
  • Include the correct CORS headers: Ensure that the server includes all the necessary headers in its CORS response. Not doing so can expose the application to security risks. For example, missing the Access-Control-Allow-Credentials header can be problematic if the browser is not returning credentials when it should. If it is set to an unintended value, the browser could be sharing credentials with an unwanted origin.
  • Document everything: It is important to adequately document your CORS policies and make them known to developers who might integrate your APIs in their application. This practice helps provide a better developer experience and builds trust with your API’s consumers.
  • Validate credentials: CORS ignores credentials by default. If you need to include credentials (such as cookies or HTTP authentication credentials) in cross-origin requests, set Access-Control-Allow-Credentials to true. However, you must also ensure that the server validates and handles credentials securely.
Tags:

What do you think about this topic? Tell us in a comment below.

Comment

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 thoughts on “What is CORS?

    Great article Gbadebo. Thank you for the education

    Hi Gbadebo Bello its really simply and superb after I research lot of articles about CORS finally I got good article fro you hope you will provide nice and understandable articles regards cyber security more from you.
    Thanks
    Harsha