Get rid of CORS origin or resource sharing error [Spring Boot-Angular]:

Radhika Inguva
8 min readApr 23, 2022

Sometimes when you are making a http request to a third-party server API or your own API but from a different domain server, we will get this error “blocked by CORS origin policy”.

So, in other words, this error appears when we want to consume the exposed endpoints of REST API lying on other server and/or port number.

By default, browsers will only the communicate between client and server to share data as long as they are from the same origin or domain called same origin policy.

What is CORS?

CORS stands for Cross Origin Resource Sharing is a standard that manages communication between 2 or multiple domains.

It is a security mechanism that will let any client can share or consume data from any domain. This concept is used for security purpose where we can have fully control on your application, like who can access our application.

A web application executes a cross-origin HTTP request when it requests a resource (Images, Scripts, CSS files, etc.) that has a different origin (domain, protocol, or port) from its own.

Cross-origin requests, however, mean that servers must implement ways to handle requests from origins outside of their own. CORS allows servers to specify who (i.e., which origins) can access the assets on the server, among many other things.

Most of the API’s, these days have CORS enabled as they are meant to be consumed by a different origin or domain.

Prerequisites

This is the list of all the prerequisites for the demo application you are going to build:

  • Java >= 1.8
  • Eclipse IDE
  • Spring Boot 2.6.5
  • Maven 3.6.x
  • Postman
  • Visual Studio code
  • Node.js version: 16.14.2
  • NPM version: 8.5.0
  • Angular CLI version:13.3.0.

For resolving CORS, we first developed spring Boot Rest API (main, controller, Entity classes are shown below) running on our localhost under port number: 1234 as Backend application with endpoint that is exposed is:

http://localhost:1234/api/v1/employees for getALL employees.

Controller:

Entity:

Main Class:

Application.properties:

Repository:

Pom dependencies:

List of dependencies in our demo example:

1. spring-boot-starter-data-jdbc

2. spring-boot-starter-data-jpa

3. spring-boot-starter-web

4. spring-boot-devtools

5. javax.persistence-api

6. spring-boot-starter-data-jpa

7. springdoc-openapi-ui

8. postgresql

9. spring-boot-starter-test

10. spring-boot-starter-validation

Project Structure:

Our application is up and running, here is the response screen.

Also, in order to generate CORS error, we have developed and angular application (module, component, service classes are shown below), which is running on (same machine in this case, can be any machine) localhost with port number 4200 as front-end.

app.module.ts class:

app.component.html

Created employee type script class: (has the properties and holds the data from http client request)

Next created employee-list component (it performs the Read operation to display list of employees on webpage.

employee-list.component.ts class:

employee-list.component.html:

Next created employee service class(it will have common logic , here it has logic of interacting with HttpClient, which will make rest API calls)

Employee-service class

App module is injected with Employee-List Component and imported with Httpclient, Employee-list component is injected with Employee service. Employee service is injected with Httpclient.

For fetching the employee record from backend application, we invoked the Http service via Employee service.

Run the backend application, recompile and run the front-end application. We can access angular server with url: http://localhost:4200/

Now, CORS issue is inevitable to occur when frontend tries to access backend both are on different port or domain.

How it is handled?

Not always we have access to backend code for modifications. In those scenarios, we can simply make necessary changes in front-end like shown below:

1.Fixing cors Issue in angular by Enable CORS with proxy configuration settings.

To enable CORS via proxy configuration.

1. Create a file proxy.conf.json in your project’s src/ folder.

2. Add the following content to the new proxy file:

{
“/api”: {
“target”: “http://localhost:1234",
“secure”: false
}
}

Meaning for above piece of code: Calls to ‘/api’ should be navigated to target : our backend server(http://localhost:1234).

Secure: is false since we are not using any https here.

3. In the CLI configuration file, package.json, add the proxyConfig option to the serve target:

Change

“start”: “ng serve”

to

“start”: “ng serve — proxy-config proxy.conf.json”

4. To run the development server with this proxy configuration, call ng serve.

To Rewrite the URL path

The pathRewrite proxy configuration option lets you rewrite the URL path at run time. For example, specify the following pathRewrite value to the proxy configuration to remove "api" from the end of a path.

If you need to access a backend that is not on localhost, set the changeOrigin option as well.

For example:

{
“/api”: {
“target”: “http://npmjs.org",
“secure”: false,
“pathRewrite”: {
“^/api”: “”
},
“changeOrigin”: true
}
}

So, if change origin is false, this implies that we can do the proxy call only from local host, if change origin is true, we can do this proxy call to remote server.

To help determine whether your proxy is working as intended, set the logLevel option. For example:

{ “/api”: {
“target”: “http://localhost:1234",
“secure”: false,
“pathRewrite”: {
“^/api”: “”
},
“logLevel”: “debug”
}
}

Proxy log levels are info (the default), debug, warn, error, and silent.

Now, we are setting proxy in frontend. When we pass all the API calls from http://localhost:4200/ , the call is handover to a proxy server (an inbuilt intermediate server from webpack. It will route our API calls to actual server and while coming back it will add the access-control-allow-origin-header also in the response, so that the CORS issue can be avoided.), then to backend server Spring Boot API. http://localhost:1234/api/v1/employees.

So, proxy server acts as a layer between these.

So in our example, in Employee service class,

http.get<Employee[]>(‘/url/api/v1/employees’);

when above line of code is encountered, the call is redirected to the key element “target” defined under “api” key in proxy.conf.json file, and replaces, /url with http://localhost:1234/ so the finally the request is now: http://localhost:1234/api/v1/employees.

Proxy.conf.Json file :

Package.json:

EmployeeServiceClass:

save and start server, make sure the backend application is up and running, response is now:

Observe the webpack-dev server is enabled.

Notice that the response headers has Acess-Control-Allow-Origin: *

Refer to this link from API for more info:

https://angular.io/guide/build#proxying-to-a-backend-server%5C

Drawbacks of Proxy servers:

The above method works great, but this can only be applied to development. This means we won’t get away with CORS using a proxy server in production. Angular-CLI provides this type of configuration, but not for production app bundles.

Due to this method’s simplicity, it is great to use to enable CORS in development. For a more logical and foolproof solution, we must always enable CORS on the server side.

2: Fixing CORS Issue in Spring Boot by Enable CORS with @CrossOrigin annotation.

Enabling CORS policy resource sharing for REST API:

By default CORS is not enabled in spring boot, the API provides @crossOrigin annotation from package org.springframework.web.bind.annotation.CrossOrigin for permitting cross-origin requests on specific handler classes and or handler methods. Processed if an appropriate HandlerMapping is configured.

Both Spring Web MVC and Spring WebFlux support this annotation through the RequestMappingHandlerMapping in their respective modules. The values from each type and method level pair of annotations are added to a CorsConfiguration and then default values are applied via CorsConfiguration.applyPermitDefaultValues().

The rules for combining global and local configuration are generally additive — e.g., all global and all local origins. For those attributes where only, a single value can be accepted such as allowCredentials and maxAge, the local overrides the global value.

For more information https://spring.io/guides/gs/rest-service-cors/

method level: Controller Method CORS Configuration

This @CrossOrigin annotation enables cross-origin resource sharing only for this specific method. By default, it allows all origins, all headers, and the HTTP methods specified in the @RequestMapping annotation. Also, a maxAge of 30 minutes is used. You can customize this behavior by specifying the value of one of the following annotation attributes:

· origins

· methods

· allowedHeaders

· exposedHeaders

· allowCredentials

· maxAge

Class level: Controller class level CORS Configuration

You can also add the @CrossOrigin annotation at the controller class level as well, to enable CORS on all handler methods of this class.

global level: Global CORS configuration

this is how to add CORS mapping in the application class:

You can easily change any properties (such as allowedOrigins in the example), as well as apply this CORS configuration to a specific path pattern.

We can configure on any one level,that is enough to resolve CORS.After configuring, we need not require proxy.conf.json file on angular side anymore.

Build and run the application, Now when we access application http://localhost:4200 output is:

We can always enhance our application further by configuring router to our application, implementing pagination and many more.

Conclusion: Of the above two ways, following one way (either by enabling proxy on angular or adding the @CrossOrigin annotation at any level)would resolve the CORS error.

I hope this article helps you in understanding about what is CORS, when will that occur and ways to resolve. Thank you.

--

--