How to use fetch() with CORS and credentials

Updated Jul 12, 2023#javascript#how-to#webdev

The Fetch API is a modern interface for fetching resources asynchronously over the network in a web browser environment. It provides a simple, standardized way to make HTTP requests from JavaScript.

The fetch() method is a key part of the Fetch API and is used to make HTTP requests. It can be used to perform cross-origin requests (CORS), which are requests to resources from a different domain than the origin of the current page. CORS requests require special headers from the server to indicate that it allows such requests.

To use fetch() with CORS and credentials, you need to specify some options in the second parameter of the method. The most important ones are:

  • mode: This option defines how CORS requests are handled. The default value is “cors”, which means that the browser will check the response headers for CORS compliance. If you set it to “no-cors”, the browser will not check the headers and will treat the response as opaque, meaning that you can’t access its content or status. If you set it to “same-origin”, the browser will only allow requests to the same origin as the current page.

  • credentials: This option defines whether cookies and other authentication data are sent with the request. The default value is “same-origin”, which means that credentials are only sent for requests to the same origin as the current page. If you set it to “include”, credentials are sent for all requests, even cross-origin ones. If you set it to “omit”, credentials are not sent for any requests.

  • headers: This option allows you to set custom headers for the request, such as “Content-Type” or “Authorization”. You need to make sure that the server accepts and handles these headers correctly.

Here is an example of using fetch() with CORS and credentials:

// Send a POST request with JSON data to https://example.com/api
fetch("https://example.com/api", {
  method: "POST",
  mode: "cors",
  credentials: "include",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ name: "Alice", age: 25 })
})
  .then((response) => response.json()) // Parse the response as JSON
  .then((data) => console.log(data)) // Do something with the data
  .catch((error) => console.error(error)); // Handle errors

Note that for this code to work, the server at https://example.com/api must respond with the following headers:

  • Access-Control-Allow-Origin: This header specifies which origins are allowed to access the resource. It can be either a specific origin (such as https://example.com) or a wildcard (*) to allow any origin. However, if you use a wildcard, you can’t use credentials, so you need to specify the exact origin that matches the request.
  • Access-Control-Allow-Credentials: This header indicates whether the server accepts credentials from the client. It must be set to true if you use credentials in your request.
  • Access-Control-Allow-Methods: This header specifies which HTTP methods are allowed for the resource. It can be either a list of methods (such as GET, POST, PUT, DELETE) or a wildcard (*) to allow any method. However, if you use a wildcard, you need to specify the exact method in your request.
  • Access-Control-Allow-Headers: This header specifies which custom headers are allowed for the resource. It can be either a list of headers (such as Content-Type, Authorization) or a wildcard (*) to allow any header. However, if you use a wildcard, you need to specify the exact headers in your request.

For example, the server could respond with these headers:

Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type

What is CORS?

CORS (Cross-Origin Resource Sharing) is a mechanism that allows web browsers to request and access resources from different domains than the one that served the current page. This is useful because, by default, browsers follow the same-origin policy, which restricts scripts from making requests to URLs that have a different origin (domain, scheme, or port) than the current page.

CORS works by adding new HTTP headers that let servers indicate which origins are allowed to access their resources. Browsers check these headers before sending or receiving cross-origin requests and follow the server’s instructions. CORS also requires browsers to send a preflight request for some types of requests that can modify data on the server, such as POST, PUT, or DELETE. A preflight request is an HTTP OPTIONS request that asks the server for permission to send the actual request.

Here is a simple example of how CORS works:

  • A user visits http://example.com and the page tries to fetch some data from http://service.example.com using JavaScript.
  • The browser sends a GET request to http://service.example.com with an Origin header that indicates the origin of the current page: Origin: http://example.com.
  • The server at http://service.example.com responds with the data and an Access-Control-Allow-Origin header that specifies which origins are allowed to access the resource: Access-Control-Allow-Origin: http://example.com.
  • The browser checks if the value of the Access-Control-Allow-Origin header matches the origin of the current page. If it does, it allows the script to access the response. If it doesn’t, it blocks the response and throws an error.

What are preflight requests?

Preflight requests, also known as CORS preflight requests, are a mechanism used by web browsers to determine if a cross-origin request (a request made from one domain to another) is safe to execute.

When making certain types of cross-origin requests, such as those that include custom headers or use methods other than simple GET or POST, browsers first send a preflight request (OPTIONS request) to the server hosting the requested resource. This preflight request is an additional request sent before the actual request to gather information about the server’s CORS policy.

The preflight request contains specific headers, including the Access-Control-Request-Method and Access-Control-Request-Headers, which indicate the intended method and headers of the actual request. The server then responds with headers indicating its CORS policy, allowing or denying the requested access based on the server’s configuration.

If the server responds with the appropriate CORS headers that grant access to the requested resource, the browser proceeds with sending the actual request. Otherwise, the browser blocks the request, and JavaScript running in the web page cannot access the response.

Preflight requests are a crucial part of enforcing security in cross-origin requests, as they prevent unauthorized access to sensitive resources and protect against cross-site request forgery (CSRF) attacks. They allow servers to specify the allowed origins, methods, headers, and other restrictions, ensuring that only authorized requests are executed.

What are user credentials?

Cookies, authorization headers, and TLS client certificates are different types of credentials that can be used to identify the user or the client when making requests to a web server. Here is a brief explanation of each type:

  • Cookies are small pieces of data that are stored by the browser and sent with every request to the same origin. Cookies can be used to store session information, preferences, or other data that the server needs to keep track of the user. Cookies can be set by the server using the Set-Cookie header or by the client using JavaScript. Cookies can also have attributes that control their scope, expiration, security, and accessibility.

  • Authorization headers are HTTP headers that contain authentication information, such as a username and password, a token, or a key. Authorization headers can be used to implement various authentication schemes, such as Basic, Bearer, Digest, or OAuth. Authorization headers can be set by the client using XMLHttpRequest, Fetch, or other libraries. Authorization headers can also be validated by the server using various methods, such as hashing, encryption, or signature verification.

  • TLS client certificates are digital certificates that are issued by a trusted certificate authority (CA) and installed on the client device. TLS client certificates can be used to prove the identity of the client when establishing a secure connection with the server using TLS (Transport Layer Security). TLS client certificates can also be used to encrypt and sign the data exchanged between the client and the server. TLS client certificates can be requested by the server using the CertificateRequest message during the TLS handshake.