Most tech developers that builds a full stack application for their first time likely deal with an unusual and famous issue : cors policy.
This raw issue subsequently break the app, or stop the loading progress of a web page in the browser. Unlikely than a simple reference error , this one doesn't explicitly point to any area in particular to focus on and figure out what exactly interrupt the page. There is just one way left. To find online which cause(s) are symptomatic of the problem you are facing. And then come back for specific area in your program to get a fix. Generally, walking through that process, we experience a point where the meaning of the problem is enough comprehensible to us. But we still get lost on where to start our troubleshooting.
And from a click, this error become a frustrating and overwhelming one. The pain is still give us, start standing unbearable. At this time, bewildered, we often ask ourself : "why the internet has to bring up this type of policy ?"
To take a road answer for this. This article, intend to navigate the readers through what CORS really means. The essential purpose behind it, the exact description of different Errors that could be delivered, while taking a view over the browsers' tools necessary to help spot in a minimal amount of times the anomalies yield by the CORS policy, saving you times and a lost of energy when you are down coding your app.
Overview
Web is flooded with devices and software applications. They quietly exchange information on almost different levels all the time. For that case a proper security need to be set in place for data to move from one place to another. Particularly In computing network , one of the best way to represent a communication is using the OSI Model approach. This network model of communication contains 07 layers of operation: application, presentation, session, transport, network, data link, physical. The application layer is where cors errors happen, it is the higher top layer in the model that connect directly with the browser. To be brief and simple, a very specific cause of the error is a non-conform request coming from a client-side(browser, AI agent, proxy, ...) in destination of a new host's computer, a server by the means of HTTP request method such as : GET, POST, DELETE, and so on.
The diagram above describes how XMLHttpRequest Object make such a request, to pull or send data in or out a server. XMLHttpRequest Object mechanism to fetch data, is an older one than fetch api or axios, but still, remains good when it comes to present how information flows from one place to another during a particular request. Just look the diagram and see how it goes.
As a matter of fact, in the way CORS technology was implemented. It wasn't from the necessity of simulating a typical request's error under the browser.
The main duty of CORS back to their implementation is to bring a safe and secure transit of data between two different domains. Since the same origin policy(policy that protect sensitive data to not being compromise from malicious script coming from the DOM when communication is open between two different domains), a technology built before where not allowing request from two different domains. To address these limitations , CORS was created to make communication soft and reliable while one resource try to access another resource remotely. By definition, CORS, stand for Cross Origin Resources Sharing. It's a help to match the need of modern website where large an sophisticated data for running is needed. If it wasn't for CORS. There will be no secure connection between your local machine and a server.
HTTP Errors
HTTP Errors sometimes cause CORS issue. Specifically to understand why. We need to make a differentiation between the two HTTP request that exist :
- simple request
- non simple request
That sounds obvious. But we need to lean a little bit on how the both operates.
Simple request
In general HTTP's request involves a lot of parameters' settings before an actual request is made. No matter how, there are often three to four parameters we constantly need to operate on change: The URL, headers, body , methods.
There are others existing flags. But these four are the one most use to raise a request.
Focusing on the Method parameter we have method which do not involve manipulating/updating data like : GET, POST those belong to Simple Request.
On the other hand there is a parameter, named Content-Type that has the power to affect the kind of request we are launching. In the case where this parameter is set to one of the three following . We rest assure we are making a simple one :
- application/x-www-form-urlencoded,
- multipart/form-data
- text/plain
If not, obviously it changes to a Non-simple-Request.
The fetch api example below is a prototype of how this simple request is structured, in the javascript's front-end code :
// product-api.js (example)
fetch( 'http://localhost:5000/api/data',
methods: 'GET',
headers: {
... // bunch of others properties
'Content-Type': 'application/x-www-form-urlencoded'
},
body :new URLSearchParams({
key1: 'value1',
key2: 'value2'
}).toString()
})
)
You can see over the lines before, that 'Content-Type' when taking a value such 'application/x-www-form-urlencoded' ignite the body to have a particular raw object embedded. An Object are a core part of Javascript's concept. This syntax keep leave this request to being simple.
Non Simple request
Non Simple Request actually use method like PUT, DELETE where existing data is undoubtedly expose to change.
In Non-Simple-Request, depending on the browser. A CORS Preflight (a request's permission connection before the really one) request is sent to identify if the domain that is about to make the request has the right to access to door of the server.
In others hand simple request can switch rapidly to become a Non simple also . It all come first to the value of the Content-Type. If set to : application/json. Then we already have a non simple request. But guess what, if Content-Type have one of the previous value said in the section before. And also if our website involve accreditation by credentials there might be time where even under **GET* or POST request, the request translate to become a non-simple one.
We can see through this example below. Always using fetch :
// product-api.js
const data = { product: 'example', image: 'image123' };
fetch('http://localhost:5000/api/data',
methods: 'GET',
headers: {
... // bunch of others properties
'Content-Type': 'application/json'
},
body :JSON.stringify(data)
)
Here 'Content-Type' has taken the value of 'application/json'. Causing the request to become a non-simple one.
If we want to talk just about HTTPS errors , there are several of them that might occurs during a particular request. But the one that require most our attention are 5xx (server error) or 4xx (client error). These one are those capable of awakening a CORS' Issue. Going further we want us to remember that. But don't worry every CORS Errors identify itself inside the message error appearing under the console dev tools of our browser. Let just keep in the head that if this issue is a bouncing from HTTP errors we need to circumcise our research to servers' Http errors and clients' Http Errors.
CORS Errors
CORS as we know is fundamental for establishing communication between two domains. The mechanism is provide keep secure interconnection between devices of the same or different network. Dealing with CORS' issue will be daunting , if you don't have a proper way to go through the different step that may be their causes. In this section we will discuss the most common flagged errors by CORS, and how front-end and back-end of an application interpret data fetch or sent over a request when they occur. Setting quite enough possibility of moving around solutions to these issues. .
1.Reason: Cors Disabled
Most popular browsers disallows the use of the CORS functionality inside their default settings.
You may be skilled in one area but remember, not everyone is assertively a programmer ,and most user just need access to their favorite websites doing their things, without making request from HTTPS TO HTTPS. But now, as a growing developer you want to create what others do not see under the hood. Then you need to also tells your browser, i am developer.
For the case of mozilla firefox's browser, CORS is disabled by the content parameters under the set of a property called disable.
content.cors.disable = true
In the same way others browsers has their ways to shut down cors permanently. For mozilla for example if we change the disable property to the boolean false. It could maybe disengage the security of same origin policy. But the concern is how does it will going to affect others left parameters of the browser. Hypothetically It's for sure a risk that could create malfunction of the browser in some points. Because a browsers is a set of protocols, javascript's script, HTML page, CSS, and security network communication. There might be a lot to consider before roughly change the value of a parameters inside. Hopefully CORS on their inside possess parameters like headers where a good selection set of those, undeniably close a communication from two different domains. And one of this property is referred as Access-Control-Allow-Origin.
When you see error **CORS Disabled* that means the Access-Control-Allow-Origin is not well set.
That is how the scheme goes:
When you send a fetch request from you front-end javascript code. This request , get interpreted by the back-end and for our case , the browser before allowing the stream connection between the two remote domain will ask to CORS in the back, if the Domain in charge to sending the request has a permission to access data gathered under the server. And that is Access-Control-Allow-Origin's role.
An example of File's organization under the server side may look like underneath:
server |
|_ _ model
|
|_ _ routes |
| |_ _ product.js
|
| server.js
| package.json
In the earlier used XMLHttpRequest's Object method fetch we have two ways of settings Access-Control-Allow-Origin permission
One : by granting access to any domain coming (using: *)
product.js
Access-Control-Allow-Origin : * // on top before any syntax
Two : by allowing only one domain to communication
product.js
Access-Control-Allow-Origin : https://example-B.com
or
Access-Control-Allow-Origin : http://localhost:5000 // for local machine
These configurations while working has brought to many others difficulty in times that went not seeing solutions after times even after setting this parameters to a right value.
In modern Javascript's API library for fetch request like axios or fetch. The process is much more easier and reliable than settings directly Access-Control-Allow-Origin under api endpoint files in the back-end. NPM dependency like cors running a safe program to configure cors ( for nodejs user at back-end environment) is a good bet to use. It just take little properties' name settings to the exact value via middleware's call.
An example of this with a framework like expressjs good to build routes for our server look like below :
express.js
const express = require('express')
const app = express()
const router = app.router()
const cors = require('cors');
app.use(cors()); middleware : // Enable CORS for all origins
// or
app.use(cors({origin: ['http://localhost:3000', 'https://your-frontend-domain.com'],
optionsSuccessStatus: 200})) // enabling only origins specified
// middleware config are made in express.js with **use** method : **app.use()**
2.Reason: CORS preflight channel did not succeed
We mentioned earlier in someway that browsers need to first know if a domain is allowed to start a conversation with a server before sending a specific request to that domain. It like a pilot which call the center's board regulation of an airport to ensure the pitch he is about to land is secure and empty.That is why CORS Preflight does in priority(aside request sent by the browser before the main request)
To better understand that preflight let's start by catching the difference between an URL, a domain , and an origin.
Here below. This is an URL
URL: https://www.tech-future.com/blog/articles?username=john doe&location=middleland
A domain will refer to all the web pages that forms the entire website (e.g : www.tech-future.com), such as :
- www.tech-future.com/careers
- www.tech-future.com/blog
- www.tech-future.com/blog/articles
- www.tech-future.com/products
- ...
An origin often called BASE_URL represent a protocol, a host and a port. It looks as following :
e.g : https://www.tech-future.com
(where exactly https://www.tech-future.com:443 represent the origin, the port which here is 443 is often hidden on website scripture under the browser)
another e.g :http://localhost: 3000
Every request made from the client side via a browser need to encapsulate the origin of requester. Both from the front-end and the back-end of an application.
The origin is automatically include in CORS' headers request when sending a request using any mechanism from xmlHttpRequest to axios in the front-end of your app. Their program's structure know how to catch origin from an url provided.
Therefore a good set to avoid preflight errors will be to grant access via Access-Control-Allow-Origin.
And we see it could be done like following :
Example :
app.use(cors({origin: ['http://localhost:3000', 'https://your-frontend-domain.com'],
optionsSuccessStatus: 200}))
Simple and precise origin gathered in one array.
3.Reason: CORS request external redirect not allowed
This Error is a Triggered one that happen most the time when an URL has updates it domain either temporarily or permanently. This will be the case if the people in charge of the website are making huge update or working on some fix, bug, security or new release, and will not want to loose track with the people using their online services for their goods.
An example. If the page https://service.tld/fetchdata were requested, and the HTTP response is "301 Moved Permanently", "307 Temporary Redirect", or "308 Permanent Redirect" with a Location of https://anotherservice.net/getdata, the CORS request will fail in this manner.
Link: CORS request external redirect not allowed
To solve the problem Just reassign the targeted server domain using the new URL domain printed over the message error appearing in the console dev tools of your browser.
4.Reason: CORS request did not succeed
This error crying out loud. It is not in fact a failure of CORS.
Others part like the network connection, or plugin, or new extension can be the cause of that error.
In first place you need to check your internet connection. If there is no problem on that side. Try to relate if you recently installed a non-secure program or an extension, and try to disable these one, And try once again the request. If that doesn't help. There could be some issues hitting your network layer application. Try to look other process outside and online that could help you fix these network issues. But first of all be sure you have to deal with a really network issue not an internet connection one.
The link below will guide you to areas to further glance if having this error persists.
Link : CORS request did not succeed
5.Reason: Multiple CORS header 'Access-Control-Allow-Origin' not allowed
This error occurs when under a fetch process the cors' header parameter : Access-Control-Allow-Origin it set to multiple origins at the same time. Access-Control-Allow-Origin just allows one origin in case it is set differently than *(any origin).
product.js
Access-Control-Allow-Origin : https://example-a.com https://example-b.com // **forbidden**
If you are looking for configuring limited amount of origin to access the server. The easier way is to use dedicated program like cors npm package, that you can install and execute to hold in dedicated configurations you can take control over.
Example : The configuration discussed in the section:
2.Reason: CORS preflight channel did not succeed
Will work too. Solving the problem.
6.Reason: Credential is not supported if the CORS header 'Access-Control-Allow-Origin' is '*'
Anytime you decide to open one of your favorite website or any new one that you get excited to use . Their are party that prompt you to login or register. Imagine we have this website we love right. It has a free version and a premium version. The access you are granted for free you can guess may not be like the one you are given in the premium stage. And this is exactly due to a set of credentials that are given from low access or a high access to a website. We can think of it like regular user vs admin user. When such a website is built, users generally access their data under a thorough control by the application of the credentials they have been granted.
That means, if you decide to set Access-control-Allow-Origin to a star : '*'. Then any domain could access any page of the website. Cors will definitely says to you : NO WAY!
Why ?
Because a star: '', allows all sort kind of resource an access, and this is a mess with the really purpose of credentials: secret password or secure authentication meeting over process like **JWT Token* or oauth authentication. The logic of the error shout out loud : you can't have credentials involved and in the meanwhile allow everyone to be in without exception. That It's absurd.
A way to fix that error is to leave Access-Control-Allow-Origin to set specific URLs for interaction and further implement thorough credentials match that not come back squeezing the communication (good Oauth or JWT implementation).
// configure cors to extend access to particular origins
app.use(cors({origin: ['http://localhost:3000', 'https://your-frontend-domain.com'],
optionsSuccessStatus: 200}))
7.Reason: invalid token 'xyz' in CORS header 'Access-Control-Allow-Headers'
This error will hardly appears to you when using modern javascript technology like fetch or axios because they are specifically settings cors header property Access-Control-Allow-Headers under the hood.
This error specify that in response to the preflight sent by the browser** their is in Access-Control-Allow-Headers one or many header's names response that do not match the standard syntax expected to be. Therefore, are confusing the user-agent(browser) receiving this report in such a way that he doesn't really get the ability to interpreted those data.
8.Reason: invalid token 'xyz' in CORS header 'Access-Control-Allow-Methods'
The same reason apply to Access-Control-Allow-Methods. The preflight send a response under a set of random methods names given in config under the back-end api endpoint of the app. The user-agent(browser in our case) try to interpret them, but fail. These method names could(e.g : GET, POST, OPTIONS) not well written or additional unknown methods of the browser in that property that kill the process.
9.Reason: Did not find method in CORS header 'Access-Control-Allow-Methods'
If you directly set Access-Control-Allow-Method in a back-end api endpoint of your app like the example underneath :
product.js
Access-Control-Allow-Methods : GET, POST
You can't suddenly decide to make an update request from your frontend javascript's code using PUT. The request will not succeed. Remember, you just set the tone of Methods to be used in the back-end and it doesn't seems like PUT serve the team. That is why, CORS complains.
Remarks: It's not required to set Access-Control-Allow-Methods, Access-Control-Allow-Headers in general. If you don't any fetch's mechanism( XMLHttpProperty, Fetch, Axios, ...) will know how to handle these properties under their process.
Just write clean code and don't try to overwhelm the server with unneeded configuration.
10.Reason: CORS request not HTTP
CORS requests may only use the HTTP or HTTPS URL scheme. In case different others kind of processed URL are used to mount these request. There will be compliance coming from CORS stating that HTTP Protocol in need for request it is not seen in the syntax mounted.
Always use http URL : e.g https://example-B.com or http://localhost:5000
Don't use file redirected Url : file:// ... to make a CORS request.
Conclusion
Cors Errors are painful and difficult to address. Then we need to shape unique ways to track those issues an gain times. The 10 different cors' errors related before may lack more refinement, but we put our effort to leave clues on how they relate practically, and where they will be the area to adjust the issues. This to ensure you build full stack-app based projects with one more layer success that decrease the time is cost you to bring the project to life. Moving forwards i would like anyone that have questions , or feedbacks, to leave their comments, all to evolve to a clear article that will get users to become much familiar with CORS!
You can join me on linkedin: https://www.linkedin.com/in/ngouend-gerard-5a0584244/
or twitter: https://x.com/nest_Ngoueni
Thanks You.
Top comments (0)