In this article, we will take a look at CORS issues in Angular application, what it is, when it occurs, and how to tackle them. We will also look at how to configure local and remote scenarios to support CORS. The accompanying code is also provided on Github.
Table of Contents
- CORS: Cross-Origin Resource Sharing
- Access-Control-Allow-Origin (ACAO) policy header
- CORS issues
- Introducing NinWiki
- Project Structure
- HTTP requests with Angular, requesting villages
- So, what happened here?
- Enabling Angular CORS via Proxy
- Proxy configuration
- Passing Proxy configuration to Angular
- Running the application
- Enable CORS in Nest.Js (Node/Express) Server
- Simple Usage (Enable All CORS Requests)
- Advanced CORS options
- Static contents
- Pre-flight requests
- Production environment
CORS: Cross-Origin Resource Sharing
If you are into web technologies, then CORS may be a familiar term to you. To those who are new to it, it is a browser mechanism that enables controlled access to resources located outside of a given domain. It extends and adds flexibility to the same-origin policy (SOP) and adds resource-sharing capabilities to the browser sessions allowing only a set of “trusted” origins to access data. Visual learner? Check out a video on the topic from Dev Academy.
Angular web applications are mostly decoupled and are deployed in their own containers, and the backend application servers and databases may have different origins.
These front-end applications communicate with the backend server over the HTTP protocol, where they exchange prescribed headers to allow for the download or upload of data. CORS uses these HTTP Headers collection to enforce its specifications. The most important header is the access control that allows the origin policy header.
The ACAO header is included in the response payload from one website to a request originating from another website and identifies the permitted origin of the request. A web browser compares the ACAO with the requesting website’s origin and permits access to the response if they match.
CORS issues
CORS issues occur when services running in different origins have to pass HTTP messages. In this context, the URL being accessed differs from the location that the frontend JavaScript application is running from, and this can happen due to servers having:
- a different scheme (HTTP or HTTPS)
- a different domain
- a different port
A familiar issue if you are requesting HTTP payloads in a frontend app will be the CORS error which can be seen on a browser’s debug console log as:
Access to XMLHttpRequest at http://localhost:3000/
from origin http://localhost:4200
has been blocked by CORS policy: No Access-Control-Allow-Origin
header is present on the requested resource.
Here the remote server at http://localhost:3000/
(scheme://domain:port/
format) has blocked a GET request citing the CORS policy issue: No Access-Control-Allow-Origin
header from port 4200 where although they have the same scheme and domain, the ports differ.
To overcome the issue, let’s look at enabling CORS in an Angular application where the application must talk to a node-based backend server and fetch data over HTTP. We will do this with a new project, the NinWiki!
Introducing NinWiki
The NinWiki (Ninja Wiki) application helps Dev Ninja villages maintain intelligence networks. As you can imagine, villages have to provide intelligence to each other for their continued safety. The wiki is data-driven and numerous villages with their own servers have to communicate with each other continually via RESTful APIs. The application has many of the features that you’d expect to find in a modern API-driven application and will serve as an introduction to the fundamentals of Angular application in fetching data from a different origin.
The article will allow you to tackle CORS issues on your own, by showing how to:
- Setup CORS in your Angular application to fetch remote data successfully
- How to setup backend to allow for remote requests
Discover why thousands of developers love to learn at Web Security Academy ♥️
Learn more
Project Structure
Front-end
The NinWiki, an Angular 14 frontend application is responsible for displaying various data gathered from backend servers.
Backend server and database
We will use Nest.js, a progressive backend framework heavily inspired by Angular itself, for the demo. Nestjs by default uses Express.js (built on top of Node.js) library under the hood. Hence, every technique for using the MVC (Model-View-Controller) pattern in Express applies to Nest as well. It is also changeable to other frameworks like Fastify. We can use them to look at various CORS configurations in the backend. The backend uses Postgres SQL as the database.
Docker
The application provided here has been dockerized and can be run on a local machine or the cloud. The backend exposes three application processes, the angular a nodejs-based backend server (port 3000), and a Postgres SQL database (port 5432) for persistence. Getting started and how to seed the data are provided in the repository README.md
file.
HTTP requests with Angular, requesting villages
Using Angular’s client HTTP API for applications, the HttpClient
service class in @angular/common/http
package allows the frontend to request data from the backend API.
Let us call the HTTP method getVillages
in our API service. The method uses the HttpClient.get() method to GET an observable of villages from the backend host server.
To know more on the RxJs operators for HTTP requests view the article by Dev Academy at https://dev-academy.com/rxjs-switchmap-concatmap-mergemap-exhaustmap/
However, when you run ng serve --open
and view the frontend application’s home page (http://localhost:4200), the request is unable to fetch the list of the villages. On the Dev debug console you can see the Cross-Origin Request Blocked (CORB) error which blocked the request.
So, what happened here?
This is an error response for missing the required ACAO header, which is used to determine whether the resource can be accessed by content operating within the current origin.
Visiting the Network > Headers tab we see that the Response Headers do not contain the ACAO headers.
The response results are then blocked from being accessed by the browser if such a request fails, this can be seen in the response tab. The results can be empty but some browsers can also show results but still block the app from accessing them.
Let’s fix this error and get the wiki data!
Enabling Angular CORS via Proxy
To fix the cors issue and get the endpoint data, Angular provides its very own proxy bridge mechanism. A proxy is able to fake our server API backend origin (http://localhost:3000
) as being the same origin (http://localhost:4200
) as the app, whereas underneath the hood it’s accessing the resource from another origin.
Angular uses the underlying webpack bundler’s dev-server ability which in turn uses the http-proxy-middleware. The proxy when configured removes the restriction from accessing the source from a different origin. Let us have a look at how to configure a proxy.
Proxy configuration
Enabling CORS requires you to provide a proxy configuration file. We have created a src/proxy.conf.json
file inside the Angular src/
folder.
If you open the file you will see the following JSON config inside.
/api/*
key here is the server host route for the proxy and the nested object specifies the configuration.target
key specifies the API url we are trying to reach, for example, the server athttp://localhost:3000
, you can use any origin domain here (http://www.example.com
).secure
is set to false since we are serving the backend api over nonsecure HTTP.pathRewrite
property rewrites the request prefix path. Here /api prefix of the request is removed so when callinghttp://localhost:4200/api
now convert tohttp://localhost:3000
. This allows clear separation in requests and not collide with our own application routes.changeOrigin
property specifies that the target is on another domain different from that which the app is currently running on.logLevel
key is set to debug, the webpack then log errors in your application’s terminal.
Passing Proxy configuration to Angular
We can use two different methods to register the angular cli proxy:
-
Passing the file to the –proxy-config flag
ng serve --proxy-config src/proxy.conf.json
in the angular cli. This selects and uses the configuration file, you can have several configs. -
Modify the angular.json file and add the proxyConfig key file to the architect > serve object’s options. This sets src/proxy.conf.json file as proxy config source for the Angular app.
You can also set up the config for each environment:
We should now update our API.service.ts file, the function no longer requires the API host URL instead we will use the name that we set for the server in proxy file(/api) and call endpoints on it. Let us set the request to /api/villages
which internally redirects and fetches data from localhost:3000/villages
due to proxy.
Please make sure to restart the application on updating the proxy configuration file to have the changes take effect.
The angular application now pretends to host the API within its own origin port and can redirect requests to the backend. If we visit the http://localhost:4200/api/villages
page, we see the same results as visiting http://localhost:3000
! Remember that the proxy rewrites the path and removes the /api.
Note there are other ways (a .js or .ts config file) for proxy configuration and more options to go for a different domain or federation scenarios. Visit the official Angular proxy chapter for more.
Running the application
Now if we run ng serve --open
and visit we can see that the request was completed successfully!
We can now inspect the dev console to see that ACAO allows all header is present.
and that the Response data wasn’t blocked:
The home page displays villages successfully!
Proxy is good for development purposes but if you want to set the application for production than you will need to configure the backend itself. Let us see how we can do that without proxy.
Enable CORS in Nest.Js (Node/Express) Server
CORS in a production environment is a server-side configuration. Usually, the webserver and the frameworks provide mechanisms to allow for resource sharing policies set up.
Simple Usage (Enable All CORS Requests)
In Nest.js this can be simply done by passing the cors: true
property, to app bootstrap in the main.ts
file.
This sets the ACAO header to the wildcard (*), please note that allowing any application to request data from the server and can be a security issue.
We can now set the service request back to the server origin:
If you check it with the frontend application, you will see the request was fetched properly.
In the cli you can fire a HTTP request (here we are using the HTTPie library) to view the access-control-allow-origin header, which will be set to wildcard (*) allowing all origins.
This was a basic configuration but cors can be configured in many ways for different application requirements. CORS headers should be properly defined in respect of trusted origins for private and public servers. Let us have a look at more advanced cors options now.
Advanced CORS options
Advanced settings help configure the server properly as vulnerabilities arise primarily as misconfigurations. Nest.js provides atomic methods to allow for more advanced CORS configurations. In the main.ts
file use the explicit method enableCors()
, below is an example of the defaults for a wildcard origin:
The method is Express.js based under the hood and thus one can refer to https://github.com/expressjs/cors#configuration-options for all options here. You do not require the key cors: true
used in previous main.ts
config.
Several ACAO header directive types exist and thus the origin should be properly specified to protect web app sensitive information.
*
: Use this to allow any origin and without any credentials. This will throw an error if we try to access it with credentials. Avoid using wildcards in internal networks, trusting network configuration alone to protect internal resources is not sufficient when internal browsers can access untrusted external domains.<origin>
: Specify a single domain that is allowed access, only allow trusted sites.null
: Typically used in a sandbox where the request is coming from a file on a user’s computer rather than from a hosted web page. It is advised to avoid using this header directive due to security concerns.
Setting the origin to a custom domain (which can be set as a list as well), modifies the ACAO header.
Static contents
This cross-origin sharing standard can enable cross-origin HTTP requests for various content types like images, web fonts, and CSS Shapes from images.
Serving static content will be beyond the scope of this article.
Pre-flight requests
Pre-flight requests are for requests that are complex, request such as DELETE, PUT or PATCH needs to ask for the server’s extra permissions with OPTIONS headers before making the actual request. For example, if we try to send a DELETE method to /villages/1 resource you will see two requests made, the OPTIONS header is first checked if the Access-Control-Allow-Methods allows the said method.
The preflight protects CORS-enabled servers from receiving cross-origin requests they may not want. The OPTIONS are exchanged before the Request and payload itself. This exchange of the metadata adds to the overhead which can be overcome with caching.
Production environment
CORS is browser-side only and is not a substitute for server-side security policies and is not a replacement for server-side protection of sensitive data. Poorly configured CORS may cause more security issues as it relaxes the Same-origin policy instead, and thus is susceptible to CSRF attacks or TLS hacks. Authentication mechanisms and session management thus should still be applied for further protection.
We can use proxies like Nginx or load balancers like (AWS Coludfront) as alternatives, and provide an extra layer of configuration but this is beyond the scope of this article.
You now have more idea on how Angular handles cross-origin resource sharing and how to fix your cors issue via the angular CLI and your API backend. Hope you got the CORS confidence boost for the shiny web application you develop! Until next time.
If you are interested in learning more about building secure Web applications consider joining our flagship program Web Security Academy. It will teach you everything you need to know in that area. ⭐ Some of the actionable tips are also covered in our secure coding training article.
In this article, we’ll go through how to use the Angular CLI proxy setup to address CORS errors in our front-end Angular 13 project.
CORS, which stands for Cross-Origin Resource Sharing, enables a server to regulate which front-end JavaScript clients may access server resources. It works by delivering HTTP headers with HTTP responses that instruct web browsers whether to allow or deny frontend JavaScript code from accessing responses.
CORS headers are basic HTTP headers that instruct a browser to enable a web application operating at one origin (domain) to access particular resources from another origin’s server.
Browser security disallow you from making cross-domain requests except if the HTTP response has a Control-Allow-Origin
header with a *
value or the domain of your client.
CORS issues are framework-agnostic and may occur in any front-end JavaScript application built with plain JS, React or Vue.js, etc. but in our case, we’ll see how to solve CORS issues in the context of an Angular 13 application.
What causes CORS errors in Angular development
A front-end developer’s primary responsibility is to access back-end APIs. It is also probable that your front-end application may need to communicate with a server from a different location on a regular basis. For example, you might use your own server, or you could use a third-party API that your application needs.
You may encounter a cross-origin resource sharing (CORS) issue in any of these situations. What exactly is CORS? What are the best practices for interacting with your back-end services? How to utilize CORS in an Angular application will be explained in this post.
Because of security concerns, web browsers impose a «same origin» policy on all web applications. Browser clients are only permitted to interact with servers that share their origin. In the case of Angular, we often need to create a full-stack application with separated client and server apps. As a result, if your front end tried to access a resource from your server that is located in a location with different origins, the browser would throw an error.
Your browser must be informed that your client and server may share resources even if they are located in different places by configuring cross-origin resource sharing (CORS).
On development; since Angular CLI offers a development server that runs on localhost:4200
by default, if you use a back-end server that runs on a different domain, you may have CORS issues if your server is not correctly setup.
Even though your backend runs on localhost, it will listen on a different port, which is considered as a separate domain.
How to resolve CORS issues with Angular 13
We now understand why CORS problems may arise while implementing your Angular application. How can they be fixed?
There are two options:
- Configure the server to transmit the necessary CORS headers
- Set up the Angular CLI proxy
The apparent approach is to correctly setup the backend server, however this is not always achievable. You may not have access to the server code, for example.
Also check out an example of how to configure CORS with TypeScript and Node/Nest.js backend
Most server languages and frameworks provide easy APIs to configure CORS. For example, in PHP, you can simply add the following lines to your PHP file:
header('Access-Control-Allow-Origin: *');
In Node.js and Express server, you can use the cors
package (npm i cors --save
) as follows:
const cors = require('cors');
const express = require('express');
const app = express();app.use(cors());
In this angular tutorial, we will learn step by step how to use Angular CLI proxy to fix CORS issues.
Prepare your Angular 13 project
At this step, we expect that you alreay have an Angular project with some code to send HTTP requests and CORS. Otherwise, you need to create a project and some code for sending requests to a server.
Open a new command-line interface and navigate to the root folder of your project.
Create a proxy configuration file for Angular 13 CLI
Next, create src/proxy.conf.json
file and add the following content:
{
"/api/*": {
"target": "http://localhost:3000",
"secure": false,
"logLevel": "debug"
}
}
This configuration file specifies that any HTTP request which starts with the /app/
path will be sent to the proxy which will redirect it to the target
hostname.
The secure
option is used to enforce usage of SSL.
See all the available options from webpack dev server documentation.
Add a proxyConfig
key to angular.json
Next, open the angular.json
file and add a proxyConfig
key under the serve->options
that points to the src/proxy.conf.json
file as follows:
"architect": {
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-application-name:build",
"proxyConfig": "src/proxy.conf.json"
},
Serving your Angular 13 application
Finally, use the following command to start the dev server with this proxy configuration:
If you do any changes in the proxy configuration file afterwards, make sure to re-run the ng serve
command.
You can find more information about the proxy configuration in the Angular CLI from the docs
Conclusion
As a re-wrap, when developing with Angular 13, developers may encouter CORS errors.
Accessing back-end APIs is one of the most important tasks of a front-end developer. Furthermore, your front-end application will frequently need to connect with a server of a different origin. This might be your own server or a third-party application programming interface that your application requires.
In any of these scenarios, it’s possible that you’ll run into CORS problems if you use Angular CLI with a back-end server running on a different domain than the one provided by the CLI by default (localhost:4200
).
A separate port is used to represent a different domain even if your backend server is operating on your local machine’s IP address.
In this post, we’ll went over how to leverage the Angular CLI proxy configuration to solve CORS problems in our front-end Angular 13 project.
Servers may control which JavaScript clients can access server resources using CORS (Cross-Origin Resource Sharing). Front-end JavaScript code may access responses only if it is allowed or denied by HTTP headers that are sent with the response to an HTTP request.
HTTP headers designed for CORS instruct a browser to allow a web application from one origin (domain) to access resources from another origin’s server.
-
Author:
Ahmed Bouchefra
Follow @ahmedbouchefra -
Date:
23 Apr 2022
When you are using a backend server for your Angular app during development, when you try to request resources from your API, you may come across some CORS restrictions that prevent you from accessing data from your API. In this tutorial, we will take a quick look at how this can easily be solved with two different solutions.
But first, to better solve the issue, we need to better understand the problem first. First of all, what is CORS anyway? Don’t care about the problem? Jump to the How to fix section.
Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
What is CORS?
Cross-Origin Resource Sharing — or CORS for short — is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one domain have permission to access selected resources from a server at a different domain.
For example, if your application is hosted on https://domain-a.com
and you make a fetch request to https://api.domain-b.com/data.json
, then you might run into CORS errors if the server doesn’t allow cross-origin resource sharing because you request resources from domain-b
on domain-a
.
Why CORS happens?
For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest
and the Fetch
API follow the same-origin policy. This means that a web application using those APIs can only request HTTP resources from the same origin the application was loaded from unless the response from the other origin includes the right CORS headers.
How to Fix CORS Issues?
When it comes to fixing CORS issues in an Angular app, we can go about the problem in two different ways:
Using Angular CLI proxy
We can get around CORS issues using proxies provided by Webpack. First things first, open up your Angular project and create a new file in your src
directory called proxy.conf.json
, with the following contents:
{
"/api": {
"target": "http://localhost:3000",
"secure": false
}
}
src/proxy.conf.json
Copied to clipboard!
This will tell your dev server to proxy any requests made to the /api
endpoint and forward them to localhost:3000
. This file is essentially using the configuration of Webpack’s devServer.proxy
. You can find the list of available options on their official documentation.
Next, you need to make Angular aware of your proxy configuration, by pointing Angular to this file through your angular.json
, using a proxyConfig
key:
"architect": {
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-application-name:build",
"proxyConfig": "src/proxy.conf.json"
}
}
}
angular.json
Copied to clipboard!
Finally, with the configurations in place, now you should be able to serve your app without having CORS issues. If you need to make changes to the proxy configuration, make sure you restart your dev environment after doing so.
ng serve
Using the right headers
CORS issues can also be fixed by sending the right HTTP headers from the server. Most languages and frameworks already provide an existing package or API to configure the right headers in an easy way. For example, if you are using Express, you can use the cors package to get rid of CORS errors:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
Copied to clipboard!
If you would like to learn more about how to build scalable APIs in Express, make sure to check out the tutorial below. Thank you for reading through, happy coding! 👨💻
How to Use Express to Build a REST API
An introduction to building scalable APIs in Node
Do you want to learn more about the world of rest APIs? Learn how you can create your first API with Express in Node, using only JavaScript.