CORS - Cross Origin Resource Sharing is a protocol that enables scripts running on a browser client to interact with resources from a different origin.
For example, if an UI app wishes to make an API call running on a different domain, it would be blocked from doing so by default due to the CORS. So CORS is not a security issue/attack but the default protection provided by Web Browser to stop sharing the data/communication between different origins.
Other origins mean the URL being accessed differs from the location that the JavaScript is running from by having:
A different schema (HTTP or HTTPS)
A different domain
A different port
However, when a server has been configured correctly to allow cross-origin resource sharing, some special headers will be included. Their presence can be used to determine that a request supports CORS. Web browsers can use these headers to determine whether a request should continue or fail.
First the browser sends a pre-flight request to the backend server to determine whether it supports CORS or not. The server can then respond to the pre-flight request with a collection of headers.
Header
Discription
Example
Access-Control-Allow-Origin
Defines which origins may have access to the resource. "*" represent any origin
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods
Indicates the allowed HTTP methods for cross-origin requests
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers
response header is used in response to a preflight request which includes the Access-Control-Request-Headers to indicate which HTTP headers can be used during the actual request. "*" represent any origin
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials
Indicates whether or not the response to the request can be exposed when the credentials flag is true.
Access-Control-Allow-Credentials: true
Access-Control-Max-Age
Defines the expiration time (second) of the result of the cached preflight request
Base on the current implementation of spring security example that implemented in Custom Authentication Provider. So now, we will continue to add CORS configuration for our spring security application.
So firstly we will create the CorsConfiguration and set some parameters as the table below.
Method
Corresponding Header
Example Value
setAllowedHeaders()
Access-Control-Allow-Headers
*
setAllowedOriginPatterns()
Access-Control-Allow-Origin
*
setAllowedMethods()
Access-Control-Allow-Methods
*
setAllowCredentials()
Access-Control-Allow-Credentials
true
Then we will create corsConfigurationSource bean by creating UrlBasedCorsConfigurationSource and set the CorsConfiguration with the path pattern that we want to apply. In this example we will apply this CorsConfiguration for all path, so we will use registerCorsConfiguration() method with /**.
If you just define the bean for CORS configuration, so it will not work, you have to edit the method in the configure() by adding the method cors()... to apply your new CORS configuration in Spring Security.
Now, let's create a simple html file which contain a javascript to call api of our spring security application and this html will be served by another http web server.
Then if you are using python on your machine, then use the command below to start a simple http web server. By default it will run at port 8000.
1
python3-mhttp.server
Now, we will try starting our spring security application without CORS configuration first, so we will remove the CORS configuration as below. Then start the application, it will run at port 8080.
Now, go to the browser with address http://localhost:8000 then open network tool and console on your browser, you will see the error as below.
12345
Access to fetch at 'http://localhost:8080/v1/contact' from origin
'http://localhost:8000' has been blocked by CORS policy: Response to preflight
request doesn't pass access control check: No 'Access-Control-Allow-Origin' header
is present on the requested resource. If an opaque response serves your needs, set
the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Then, if you look into the response of the preflight request, you will see there are no headers for CORS.
So, it means that when the browser execute a script to call to another domain (http://localhost:8080) and the server of this domain has not been configured to response some required headers of CORS in the preflight request so the browser has blocked this request by default CORS policy.
Now, let's go back to our spring security application and apply the CORS configuration and start the spring security application again.
Now, let's refresh http://localhost:8000 on your browser, you will see the error has been disappear and you can call the api successfully.
Then, if you look into the response headers from spring security application in the preflight request, you will see there are some headers of CORS configuration.