Gaurav Rajapurkar - A Technology Enthusiast
9 min readDec 3, 2022

--

Understanding ๐—–๐—ข๐—ฅ๐—ฆ-๐—–๐—ฟ๐—ผ๐˜€๐˜€-๐—ข๐—ฟ๐—ถ๐—ด๐—ถ๐—ป ๐—ฅ๐—ฒ๐˜€๐—ผ๐˜‚๐—ฟ๐—ฐ๐—ฒ ๐—ฆ๐—ต๐—ฎ๐—ฟ๐—ถ๐—ป๐—ด

Understanding ๐—–๐—ข๐—ฅ๐—ฆ-๐—–๐—ฟ๐—ผ๐˜€๐˜€-๐—ข๐—ฟ๐—ถ๐—ด๐—ถ๐—ป ๐—ฅ๐—ฒ๐˜€๐—ผ๐˜‚๐—ฟ๐—ฐ๐—ฒ ๐—ฆ๐—ต๐—ฎ๐—ฟ๐—ถ๐—ป๐—ด

Overview: ๐—–๐—ข๐—ฅ๐—ฆ-๐—–๐—ฟ๐—ผ๐˜€๐˜€-๐—ข๐—ฟ๐—ถ๐—ด๐—ถ๐—ป ๐—ฅ๐—ฒ๐˜€๐—ผ๐˜‚๐—ฟ๐—ฐ๐—ฒ ๐—ฆ๐—ต๐—ฎ๐—ฟ๐—ถ๐—ป๐—ด is an HTTP-header-based method that allows a server to specify any origins (domain, scheme, or port) other than its own from which a browser should allow resources to be loaded. CORS additionally makes use of a technique that allows browsers to send a โ€œpreflightโ€ request to the server hosting the cross-origin resource to ensure that the server will allow the real request. The browser transmits headers indicating the HTTP method and headers that will be used in the real request during that preflight.

As an Application developer, We need know What is CORS and how it works ๐Ÿ”ฅ

Hereโ€™s a high level flow on how browsers initiate that extra โ€œpreflightโ€ request to determine whether they have permission to perform cross origin requests.

What is CORS ? CORS stands for Cross Origin Resource Sharing, and itโ€™s a protocol that allows servers to receive requests from different domains.

Developers often make external API requests to fetch data form external servers. Sometimes these servers could be from different domains too.

Example:
๐Ÿ‘‰ User app in domain[.]com making a GET request to domain[.]com is a same origin request
๐Ÿ‘‰ User app in domain[.]com making a GET request to google[.]com is a cross origin request

But these cross domain requests are restricted by the browser โŒ.

We get CORS errors like below:

Once developers have configured CORS on the server to accepts requests from other domains the browser will kick in a preflight check โœ…

It is to verify whether resource sharing is allowed on the destination server. The preflight request uses the HTTP method OPTIONS.

So lets take a look in more details here . Browsers use CORS, a method, to prevent websites from requesting data from different URLs.
A request from a browser includes an origin header in the request message. The browser allows it if it gets to the server of the exact origin; if not, the browser blocks it.

We can deal with CORS issues on the backend.
Cross-origin requests require that the values for origin and ๐—”๐—ฐ๐—ฐ๐—ฒ๐˜€๐˜€-๐—–๐—ผ๐—ป๐˜๐—ฟ๐—ผ๐—น-๐—”๐—น๐—น๐—ผ๐˜„-๐—ข๐—ฟ๐—ถ๐—ด๐—ถ๐—ป in the response headers match and it is set by the server.
When you add an origin to the backend code, the CORS middleware only permits this URL to communicate
with other origins and utilize it for cross-origin resource requests.

There are two ways to fix CORS issues:

๐Ÿญ. ๐—–๐—ผ๐—ป๐—ณ๐—ถ๐—ด๐˜‚๐—ฟ๐—ฒ ๐˜๐—ต๐—ฒ ๐—•๐—ฎ๐—ฐ๐—ธ๐—ฒ๐—ป๐—ฑ ๐˜๐—ผ ๐—”๐—น๐—น๐—ผ๐˜„ ๐—–๐—ข๐—ฅ๐—ฆ

Server can let all domains with ๐—”๐—ฐ๐—ฐ๐—ฒ๐˜€๐˜€-๐—–๐—ผ๐—ป๐˜๐—ฟ๐—ผ๐—น-๐—”๐—น๐—น๐—ผ๐˜„-๐—ข๐—ฟ๐—ถ๐—ด๐—ถ๐—ป: *.
This actually turns off same-origin policy, which is not recommended.
Another option would be only to allow particular domain, which is better option, e.g., ๐—”๐—ฐ๐—ฐ๐—ฒ๐˜€๐˜€-๐—–๐—ผ๐—ป๐˜๐—ฟ๐—ผ๐—น-๐—”๐—น๐—น๐—ผ๐˜„-๐—ข๐—ฟ๐—ถ๐—ด๐—ถ๐—ป: ๐—ต๐˜๐˜๐—ฝ๐˜€://๐—ฑ๐—ผ๐—บ๐—ฎ๐—ถ๐—ป2.๐—ฐ๐—ผ๐—บ.

๐Ÿฎ. ๐—จ๐˜€๐—ฒ ๐—ฎ ๐—ฃ๐—ฟ๐—ผ๐˜…๐˜† ๐—ฆ๐—ฒ๐—ฟ๐˜ƒ๐—ฒ๐—ฟ

We can use a proxy server to call external API.
It acts as a middleware between client and the server. If server doesnโ€™t return proper headers defined by CORS, we can add then in the proxy.

Once Fix is done. Below, youโ€™ll see an example of the headers sent back by the server (yes, by server โ€” therefore CORS is not something you can fix in the UI code) with a reply to OPTIONS. Look at those Access-Control-* headers and focus on Access-Control-Allow-Origin:

Hereโ€™s whatโ€™s happening: before sending your requested API call, your browser does a โ€˜security checkโ€™ by asking the API, (via an OPTIONS call, who is allowed to do what. Simple as that.

An โ€˜issue with CORSโ€™ occurs when the API does not reply to such request with, โ€˜Yes, dear browser, you are allowed to do that callโ€™. So, as you can see on the screenshot above, my API responded that my UI, localhost, is allowed to handle OPTIONS, HEAD, DELETE, POST and GET calls.

Now thatโ€™s the core of all the โ€˜problemsโ€™ with CORS. In order to fix CORS, you need to make sure that the API is sending proper headers (Access-Control-Allow-*). Thatโ€™s why itโ€™s not something you can fix in the UI, and thatโ€™s why it only causes an issue in the browser and not via curl: because itโ€™s the browser that checks and eventually blocks the calls.

How do I fix a CORS error in Java Spring boot?
Enable CORS in Controller Method We need to set the origins for RESTful web service by using @CrossOrigin annotation for the controller method. This @CrossOrigin annotation supports specific REST API, and not for the entire application.

In the simplest scenario, cross-origin communications starts with a client making a GET, POST, or HEAD request against a resource on the server.
In this scenario, the content type of a POST request is limited to application/x-www-form-urlencoded, multipart/form-data, or text/plain.
The request includes an Origin header that indicates the origin of the client code.

The server will consider the requestโ€™s Origin and either allow or disallow the request.
If the server allows the request, then it will respond with the requested resource and an Access-Control-Allow-Origin header in the response.
This header will indicate to the client which client origins will be allowed to access the resource. Assuming that the Access-Control-Allow-Origin header matches the requestโ€™s Origin, the browser will allow the request.

On the other hand, if Access-Control-Allow-Origin is missing in the response or if it doesnโ€™t match the requestโ€™s Origin, the browser will disallow the request.

Two simple ways discussed below to handle this Access-Control-Allow-Origin (CORS) issue -

  1. Put @CrossOrigin annotation on top of Controller to allow CORS as shown below-
   @CrossOrigin(origins= {"*"}, maxAge = 4800, allowCredentials = "false" )
@RestController
@RequestMapping("/")
public class CorsOk {
/* put your code here */

}
  1. A simple ways is to create a simple CORS filter to allow every type pf CORS, this can be done as shown below.
//Samplecode - for full code download the file AppCORSFilter
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

chain.doFilter(req, res);
}
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class AppCORSFilter implements Filter {

private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);

public AppCORSFilter() {
log.info("SimpleCORSFilter init");
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

}

AWS S3 also allows configuring CORS for content hosted on S3.

Regarding preflight request, if you open your browser in developer mode you will see two requests for the same resource,
the first is preflight request and if the server allow this origin, then second request will be send to consume the resource .

Using cross-origin resource sharing (CORS)

Cross-origin resource sharing (CORS) defines a way for client web applications that are loaded in one domain to interact with resources in a different domain. With CORS support, you can build rich client-side web applications with Amazon S3 and selectively allow cross-origin access to your Amazon S3 resources.

This section provides an overview of CORS. The subtopics describe how you can enable CORS using the Amazon S3 console, or programmatically by using the Amazon S3 REST API and the AWS SDKs.

Cross-origin resource sharing: Use-case scenarios
The following are example scenarios for using CORS.

Scenario 1

Suppose that you are hosting a website in an Amazon S3 bucket named website as described in Hosting a static website using Amazon S3. Your users load the website endpoint:

http://website.s3-website.us-east-1.amazonaws.com
Now you want to use JavaScript on the webpages that are stored in this bucket to be able to make authenticated GET and PUT requests against the same bucket by using the Amazon S3 API endpoint for the bucket, website.s3.us-east-1.amazonaws.com. A browser would normally block JavaScript from allowing those requests, but with CORS you can configure your bucket to explicitly enable cross-origin requests from website.s3-website.us-east-1.amazonaws.com.

Scenario 2

Suppose that you want to host a web font from your S3 bucket. Again, browsers require a CORS check (also called a preflight check) for loading web fonts. You would configure the bucket that is hosting the web font to allow any origin to make these requests.

How does Amazon S3 evaluate the CORS configuration on a bucket?
When Amazon S3 receives a preflight request from a browser, it evaluates the CORS configuration for the bucket and uses the first CORSRule rule that matches the incoming browser request to enable a cross-origin request. For a rule to match, the following conditions must be met:

The requestโ€™s Origin header must match an AllowedOrigin element.

The request method (for example, GET or PUT) or the Access-Control-Request-Method header in case of a preflight OPTIONS request must be one of the AllowedMethod elements.

Every header listed in the requestโ€™s Access-Control-Request-Headers header on the preflight request must match an AllowedHeader element.

Browser support
CORS is supported by all browsers based on the following layout engines:

  1. Blink- and Chromium-based browsers (Chrome 28+,Opera 15+, Amazon Silk, Androidโ€™s 4.4+ WebView and Qtโ€™s WebEngine)
  2. Gecko 1.9.1 (Firefox 3.5 SeaMonkey 2.0) and above.
  3. MSHTML/Trident 6.0 (Internet Explorer 10) has native support.
  4. MSHTML/Trident 4.0 & 5.0 (Internet Explorer 8 & 9) provide partial support via the XDomainRequest object.
  5. Presto-based browsers (Opera) implement CORS as of Opera 12.00[14] and Opera Mobile 12, but not Opera Mini.
  6. WebKit (Initial revision uncertain, Safari 4 and above, Google Chrome 3 and above, possibly earlier).
  7. Microsoft Edge All versions.

History
Cross-origin support was originally proposed by Matt Oshry, Brad Porter, and Michael Bodell of Tellme Networks in March 2004 for inclusion in VoiceXML 2 to allow safe cross-origin data requests by VoiceXML browsers. The mechanism was deemed general in nature and not specific to VoiceXML and was subsequently separated into an implementation .
The WebApps Working Group of the W3C with participation from the major browser vendors began to formalize the NOTE into a W3C Working Draft on track toward formal W3C Recommendation status.

In May 2006 the first W3C Working Draft was submitted.[20] In March 2009 the draft was renamed to โ€œCross-Origin Resource Sharingโ€[21] and in January 2014 it was accepted as a W3C Recommendation.

CORS vs JSONP
CORS can be used as a modern alternative to the JSONP pattern. The benefits of CORS are:

While JSONP supports only the GET request method, CORS also supports other types of HTTP requests.
CORS enables a web programmer to use regular XMLHttpRequest, which supports better error handling than JSONP.
While JSONP can cause cross-site scripting (XSS) issues when the external site is compromised, CORS allows websites to manually parse responses to increase security.
The main advantage of JSONP was its ability to work on legacy browsers which predate CORS support (Opera Mini and Internet Explorer 9 and earlier).
CORS is now supported by most modern web browsers.

Hope this post on CORS was helpful.

Happy Coding โ€ฆโ€ฆ.

Other Interesting Articles :

Many ways to learn GCP for Free with Google Cloud over the holidays

Linux Commands for Cloud Learning

--

--

Gaurav Rajapurkar - A Technology Enthusiast

An Architect practising Architecture, Design,Coding in Java,JEE,Spring,SpringBoot,Microservices,Apis,Reactive,Oracle,Mongo,GCP,AWS,Kafka,PubSub,DevOps,CI-CD,DSA