Preflight Requests: A Beginner's Guide

AanchalAanchal
6 min read

What is a preflight request?

A preflight request is a special type of HTTP request that is sent by a browser to a server before making a cross-origin request. The preflight request is used to determine if the server will allow the cross-origin request and what headers the server will accept.

Browser requesting for Preflight request before Actual request

A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood and if a server is aware of using specific methods and headers.

It is an OPTIONS request, using three HTTP request headers: Access-Control-Request-Method, Access-Control-Request-Headers, and the Origin header.

Headers information for a Preflight Request

A preflight request is automatically issued by a browser and in normal cases, front-end developers don't need to craft such requests themselves. It appears when the request is qualified as "considered to be preflighted" and omitted for simple requests.

Preflight requests are sent for requests that are considered to be "potentially dangerous". These requests include requests that:

  • Use the POST, PUT, DELETE, or PATCH methods

  • Set cookies

  • Read or modify local storage

  • Send credentials (such as a username and password)

For example, a client might be asking a server if it would allow a DELETE request, before sending a DELETE request, by using a preflight request:

OPTIONS /resource/foo
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: origin, X-Requested-With
Origin: https://foo.bar.org

The purpose of this code example is to demonstrate how a client can make a preflight request to a server to check if it is allowed to make a cross-origin request. The server will respond with appropriate CORS headers, which specifically indicate whether the cross-origin request is allowed or not.

  • OPTIONS /resource/foo: This line represents the HTTP request line, where OPTIONS is the HTTP method used to make the request, and /resource/foo is the path of the resource being accessed.

  • Access-Control-Request-Method: DELETE: This line is a request header that specifies the HTTP method (DELETE) that will be used in the actual request if the preflight request is successful.

  • Access-Control-Request-Headers: origin, x-requested-with: This line is a request header that lists the additional headers (origin and x-requested-with) that will be included in the actual request if the preflight request is successful.

  • Origin: https://foo.bar.org: This line is a request header that specifies the origin (i.e. the domain) from which the actual request will be made.

If the server allows it, then it will respond to the preflight request with an Access-Control-Allow-Methods response header, which lists DELETE:

HTTP/1.1 204 No Content
Connection: keep-alive
Access-Control-Allow-Origin: https://foo.bar.org
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 86400

The preflight response can be optionally cached for the requests created in the same URL using Access-Control-Max-Age header like in the above example. To cache preflight responses, the browser uses a specific cache that is separate from the general HTTP cache that the browser manages. Preflight responses are never cached in the browser's general HTTP cache.

How a Preflight Request Works?

The server checks which methods, headers, and content types are allowed for the requested resource. Once that’s evaluated, the server responds accordingly with appropriate Cross-Origin Resource Sharing (CORS) headers. These headers specifically indicate whether the cross-origin request is allowed or not. We’ll dive deeper into these CORS headers later in this post.

By making necessary changes in your server, you can allow these preflight requests and ensure that the applications which want to access resources from your server can do so without violating the same-origin policy.

Why are preflight requests necessary?

Preflight requests are necessary because the Same-Origin Policy (SOP) prevents browsers from making cross-origin requests by default. The SOP is a security feature that helps to protect users from cross-site scripting (XSS) attacks and other security threats.

However, the SOP can also prevent legitimate cross-origin requests, such as requests to fetch data from an API. Preflight requests allow browsers to make these legitimate cross-origin requests by first checking with the server to see if it will allow the request.

What are the headers used in a preflight request?

OPTIONS /resource HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization

The following are the most common headers used in a preflight request:

  • Origin: This header tells the server the origin of the request, which is the domain name and port number of the website that is making the request.

  • Access-Control-Request-Method: This header tells the server the method that will be used for the actual request.

  • Access-Control-Request-Headers: This header tells the server the names of the headers that will be sent in the actual request, such as Content-Type and Authorization.

How does a server respond to a preflight request?

The server can respond to a preflight request with a number of different headers, including:

  • The Access-Control-Allow-Origin header tells the browser whether the cross-origin request is allowed. The value of this header can be a wildcard (*), which means that all origins are allowed, or it can be a specific origin, such as the domain name and port number of the website that is making the request.

  • The Access-Control-Allow-Methods header tells the browser which methods are allowed for the cross-origin request. The value of this header is a comma-separated list of methods, such as GET, POST, PUT or DELETE.

  • The Access-Control-Allow-Headers header tells the browser which headers are allowed in the cross-origin request. The value of this header is a comma-separated list of headers, such as Content-Type and Authorization.

  • The Access-Control-Max-Age header tells the browser how long the results of the preflight request can be cached in the browser's memory. The value of this header is an integer, in seconds.

If the server responds to the preflight request with a 200 OK status code, the browser will automatically send the actual cross-origin request. If the server responds with any other status code, the browser will not send the actual request.

What if the server does not respond to a preflight request?

If the server does not respond to a preflight request, the browser will not send the actual cross-origin request. This is because the browser does not know if the server will allow the request or what headers the server will accept.

How can I prevent preflight requests?

If you are a server administrator, you can prevent preflight requests by setting the Access-Control-Allow-Origin header to a wildcard (*). This will allow all origins to make cross-origin requests without having to send a preflight request first.

However, it is important to note that doing this can make your server more vulnerable to XSS attacks and other security threats. Therefore, it should only be done if we are confident that the server is secure.

Conclusion

Preflight requests are a security feature that can help to protect users from cross-site scripting (XSS) attacks and other security threats. By requiring servers to explicitly allow cross-origin requests, preflight requests can help to ensure that only trusted servers are able to access user data. However, preflight requests can also add latency to cross-origin requests or prevent legitimate requests. Therefore, it is important to use preflight requests only when necessary.

0
Subscribe to my newsletter

Read articles from Aanchal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Aanchal
Aanchal