Figuring Out Cross Origin Requests
What are Cross Origin Requests (CORS)?
CORs is a mechanism that allows websites on one origin to be able to request data from another origin.
Definition of Origin
2 URLs are considered of the same origin if they have the same host
,
scheme
, and port
(if specified).
Host: meaning the domain name like foo.com
or foo.org
Scheme: whether it is http
or https
Port: the port number
Examples
URL A | URL B | Same Origin? |
---|---|---|
foo.com | foo.org | No. they don’t have the same host |
http://foo.com | https://foo.com | No. they have different schemes |
foo:1234.com | foo:9000.com | No. they have different port numbers |
https://foo.com | https://foo.com | Yes. |
How Same-Origin Policy Works
All web browsers implement a security mechanism called same-origin policy
. It
makes sure the your webpage is not able to receive aka read data from a
different origin.
Example of Same-Origin Policy
Let’s say you have a website called https://funkyshoes.com
and your
javascript wants to make an API request to another origin, something like
https://api.funkyshoes.com
. The request will go through and will return a
response but the user’s web browser will block the response so that the
javascript from https://funkyshoes.com
will not be able to see it.
How To Relax The Same-Origin Policy
Access-Control-Allow-Origin: *
The Access-Control-Allow-Origin
response header is used to indicate to a
browser that it’s OK to share a response with a different origin.
Using a *
means that we allow our web page to receive data from any
origin.1 To allow a specific domain, simply set the header with the domain
name.
Access-Control-Allow-Origin: https://example.com
⚠️ Warning: you can only specify EXACTLY ONE ORIGIN.
A Workaround The Origin Limit
Create a enableCors
middleware. create a list of your allowed origins and
once the request comes in, check the origin from the header against your list.
AKA whitelist your origins.
First, we will need to check that the request Origin
header is an exact,
case-sensitive match of the allowed origins. If the origin is allowed, we then
set the Access-Control-Allow-Origin
header with the origin that was sent with
the request (the Origin
header). Since the headers of the response will be
different, a Vary: Origin
2 header will need to be set in order to warn any
caches that the response may be different.
TLDR;
- Create a list of allowed origins
- Check that the request’s
Origin
header is an exact, case-sensitive match of allowed origins - If the origin is allowed, set the
Access-Control-Allow-Origin
with the same exact origin - Also add a
Vary: Origin
header to the response
Authentication With CORS
If an API requires authentication, then the Allow-Control-Allow-Credentials: true
3
header should also be set.
Preflight CORs Request
When the browser need to make a cross-origin request, sometimes it will send a
preflight request
first. The purpose of this is to determine whether or nothe
real cross-origin request will be permitted by the server.
When the browser sends a preflight request, these are the relevant headers that will be checked by the server to identify it as a preflight request.
CORs Origin — Lets the API know what origin the preflight request is coming from.
Access-Control-Request-Method — Lets the API know what HTTP method will be used for the real request.
Access-Control-Request-Headers — lets the API know what HTTP headers will be sent with the real request. Note that it won’t list all the headers that the real request will use.
Preflight requests always have 3 components:
- HTTP Method OPTIONS
- Origin header
- Aceess-Control-Request-Method header
How it works
- Browser sends preflight request
- server identifies request as a preflight
- server sends a
200 OK
response with special headers. Allowing the real CORs request to proceed.
Special Headers in the 200 OK
response:
- Aceess-Control-Allow-Origin
- reflects the value of the preflight’s
Origin
header
- reflects the value of the preflight’s
- Aceess-Control-Allow-Methods
- list of HTTP methods that can be used in real cross-origin requests
- Aceess-Control-Allow-Headers
- list of request headers that can be included in real cross-origin requests
Example:
Access-Control-Allow-Origin: <reflected trusted origin>
Access-Control-Allow-Methods: OPTIONS, PUT, PATCH, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type
Why a 200 OK
status rather than a 204 No Content
status?
Some browsers do not support the 204 response status and will block the real request.
Optional Header To Add To Preflight response
Access-Control-Max-Age
: number of seconds that the information provided by
Access-Control-Allow-Methods
and Access-Control-Allow-Headers
can be cached
by browsers.
-1 means to disable it.
Browsers have their own default value for Access-Control-Max-Age
but may also have
a cap on how long the headers can be cached for4.
Footnotes
-
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin ↩
-
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary ↩
-
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials ↩
-
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age#directives ↩