XMLHttpRequest blocked by CORS policy annotation #CrossOrigin - spring

Access to XMLHttpRequest at 'http://localhost:8080/api/auth/signup' from origin 'https://mysuite.ru' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
http.cors().and()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/admin").hasRole("ADMIN")
.antMatchers("/").permitAll()
.antMatchers("/favicon.ico").permitAll()
.antMatchers("/static/**").permitAll()
.antMatchers("/manifest.json").permitAll()
.antMatchers("/logo192.png").permitAll()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/test/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
#RestController
#RequestMapping("/api/auth")
#CrossOrigin(origins = "*", maxAge = 3600)
public class AuthController {
Redirecting via nginx
server {
listen 443 ssl;
server_name is my address.ru;
ssl_certificate C:/ssl/ip.crt;
ssl_certificate_key C:/ssl/ip.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:8080;
proxy_set_header Host $http_host;
proxy_redirect off;
}
}
UPDATE
Request Headers:
Accept: application/json, text/plain, */*
Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-
Modified-Since,Cache-Control,Content-Type,Range
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Length,Content-Range
Content-Type: application/json;charset=UTF-8
Referer
sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Yandex";v="21"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/92.0.4515.159 YaBrowser/21.8.3.614 Yowser/2.5
Safari/537.36
Add in nginx:
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://localhost:8080;
}
No result yet

Try adding the methods attribute to #CrossOrigin. When used to annotate a method, the supported methods are the same as the ones to which the method is mapped, but since you are using it at the class level you might need to specify them as follows:
#CrossOrigin(origins = "*", maxAge = 3600, methods = {RequestMethod.GET, RequestMethod.POST} ) // Just an example

Try replacing your #CrossOrigin annotation with
#CrossOrigin(value = "https://mysuite.ru", allowCredentials = "true")
Don't use "*" as an origin but "https://mysuite.ru".

The problem was that I was mistakenly doing a post request on the front side to localhost

Related

NGINX CORS Issues

There is a server with NGINX 1.16, which is used to upload files through AJAX
Here are the configuration settings of the NGINX file
location ~ \.php$ {
include snippets/fastcgi-php.conf;
#
# With php-fpm (or other unix sockets):
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
# With php-cgi (or other tcp sockets):
#fastcgi_pass 127.0.0.1:9000;
if ($request_method = "OPTIONS") {
add_header Access-Control-Allow-Origin 'http://myserver.com';
add_header Access-Control-Allow-Credentials false;
add_header Access-Control-Allow-Methods 'DELETE,GET,OPTIONS,POST,PUT';
add_header Access-Control-Allow-Headers 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,X-Token-Auth,X-Mx-ReqToken,X-Requested-With';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
add_header Access-Control-Allow-Origin 'http://myserver.com';
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods 'DELETE,GET,OPTIONS,POST,PUT';
add_header Access-Control-Allow-Headers 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,X-Token-Auth,X-Mx-ReqToken,X-Requested-With';
}
Here are the test results for CURL
When you try to upload a file, a CORS error is displayed in the console
Maybe someone came across a similar behavior when СORS is turned on on the server, but an error pops up anyway?
UPD: It has also been noticed that headers are not displayed in the browser. There is an assumption that this is the reason, but then how to “force” the server to give headers?
add_header Access-Control-Allow-Origin 'http://myserver.com'; is wrong in your setting.
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}

How to configure my NGINX to allow CSRF protection on my Spring Boot application

I am trying to separate my Spring Boot application from my front-end, namely my Angular 7+ application, by using an NGINX reverse proxy.
My Spring Boot application is of version 2.0.3+.RELEASE and has CSRF protection enabled.
My Security configuration looks like the following:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().and()
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and().csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
My nginx.conf looks like this:
events {
worker_connections 768;
}
http {
# Nginx will handle gzip compression of responses from the app server
gzip on;
gzip_proxied any;
gzip_types text/plain application/json;
gzip_min_length 1000;
server {
listen 80;
# Nginx will reject anything not matching /api
location /api {
# Reject requests with unsupported HTTP method
if ($request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|DELETE)$) {
return 405;
}
# Only requests matching the whitelist expectations will
# get sent to the application server
proxy_pass http://app:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
}
location / {
root /var/www/ui;
try_files $uri $uri/ /index.html =404;
index index.html index.htm;
}
}
}
Considering the following Request Header for http://localhost/api/myResource I get a Forbidden message on POST request:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: it,it-IT;q=0.9,en;q=0.8,it-CH;q=0.7
authorization: Basic
Connection: keep-alive
Content-Length: 94
Content-Type: application/json
Cookie: SESSION=MTdmNGFmODctMTNiMC00YzRjLWJjNTAtYmVlMTgzMzJkZTli; XSRF-TOKEN=fbe30e1e-1f64-4910-9040-799217c59b51
Host: localhost
Origin: http://localhost
Referer: http://localhost/admin/bundles
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
X-Requested-With: XMLHttpRequest
The Spring application logs the following error:
Invalid CSRF token found for http://localhost/api/myResource
NON GET calls should pass in X-XSRF-Token in header when calling backend spring boot server to this explicity ,
#Injectable()
export class CustomInterceptor implements HttpInterceptor {
constructor(private http: Http,private tokenExtractor: HttpXsrfTokenExtractor) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const headerName = 'X-XSRF-TOKEN';
let token = this.tokenExtractor.getToken() as string;
console.log(token)
if (token !== null && !request.headers.has(headerName)) {
request = request.clone({ headers: request.headers.set(headerName, token) });
}

Nginx PHP API CORS

I'm developing the SPA with VueJS which should operate with PHP API/Nginx on the remote domain. Of course I've faced the CORS problem.
Here is the recent Nginx config file:
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE, HEAD';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,some_my_tokens';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' '1728000';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Origin,Content-Type,Accept,Authorization,some_my_tokens';
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' '0';
return 204;
}
try_files $uri $uri/ /index.php?$args;
}
I'm still getting Errors "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://remote_host:8080' is therefore not allowed access.".
Please help.
Add below code in your index.php
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // cache for 1 day
}
// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
}
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
}
exit(0);
}
In my case, when our backend was sending an error response, for example in PHP header('HTTP', ERROR_CODE), was resulting in CORS headers missing from response.
Adding the always parameter to these CORS headers fixed the issue:
add_header Access-Control-Allow-Origin $http_origin always;
As the docs states about add_header directive
Adds the specified field to a response header provided that the response code equals 200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13), or 308 (1.13.0).
and docs says about always parameter
If the always parameter is specified (1.7.5), the header field will be added regardless of the response code.
The reason it's saying No 'Access-Control-Allow-Origin' header is present on the requested resource is because.....
wait for it....
no 'Access-Control-Allow-Origin' header is present on the requested resource.
You have this directive in your location block:
add_header 'Access-Control-Allow-Origin' '*';
But then you have an if condition for OPTIONS requests, and within that level you don't have an Access-Control-Allow-Origin header.
From the docs
There could be several add_header directives. These directives are
inherited from the previous level if and only if there are no
add_header directives defined on the current level.
So your OPTIONS preflight will be missing the header.
I'd suggest using more_set_headers on nginx.conf instead of add_header, for example:
location / {
more_set_headers 'Access-Control-Allow-Origin' '*';
more_set_headers 'Access-Control-Allow-Credentials' 'true';
more_set_headers 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE, HEAD';
more_set_headers 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,some_my_tokens';
if ($request_method = 'OPTIONS') {
more_set_headers 'Access-Control-Max-Age' '1728000';
more_set_headers 'Access-Control-Allow-Credentials' 'true';
more_set_headers 'Access-Control-Allow-Headers' 'Origin,Content-Type,Accept,Authorization,some_my_tokens';
more_set_headers 'Content-Type' 'text/plain; charset=UTF-8';
more_set_headers 'Content-Length' '0';
return 204;
}
try_files $uri $uri/ /index.php?$args;
}
The more_set_headers directive is part of the HttpHeadersMore module which is included in the nginx-extras flavor of nginx, you can install it on ubuntu 16 by doing:
sudo apt-get install nginx-extras

Is it possible to forward a get request using nginx proxy to the same url with port

I have a simple python bottle api, and a nginx server that host the index.html that makes ajax request to the bottle api running on the local host on port 8001. The problem is I don't handle the CORS because its running in a closed env and its just a simple api to manage some active directory stuff and it sits behind a firewall and basic auth. I'm not really worried about cross site scripting. What I need to know is if I program my ajax request from
$.ajax({
type: "GET",
url: "http://localhost:8001/newuser/" + "firstName=" + fname + "&lastName=" + lname + "&email=" + email + "&password=" + new_password,
success: function(data){
alert(data);
document.getElementById("alert").innerHTML = data.toString();
}
});
to
$.ajax({
type: "GET",
url: "/newuser/" + "firstName=" + fname + "&lastName=" + lname + "&email=" + email + "&password=" + new_password,
success: function(data){
alert(data);
document.getElementById("alert").innerHTML = data.toString();
}
});
how do I write the nginx rewrite to take the ajax request and make it goto port 8001 at local host, and if thats even possible. I looked at a few examples but couldn't quite find what I needed.
Can someone help me with the nginx code for this, I need to forward the request to localhost at :8001 and not :80 when /newuser/ is detected.
This is because when I call localhost:8001 it gives me a cors error in the web console.
I tried to disable CORS in nginx
nginx config
location * {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
virtual nginx config
location * {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
Here is my solution I figured it out.
#
# A virtual host using mix of IP-, name-, and port-based configuration
#
upstream admanager.oneplatform.build {
server localhost:8001;
}
server {
listen 80 default_server;
server_name _;
root /opt/admanager1;
index index.html;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
location /newuser/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:8001/newuser/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
}
location /update/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:8001/update/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
}
}

Error: Content-Type is not allowed by Access-Control-Allow-Headers

I am getting this error in Chrome when trying to send an ajax request:
Content-Type is not allowed by Access-Control-Allow-Headers
Everything works fine in Firefox.
Can anyone help me to resolve this issue?
I solved the problem adding to Apache Web Server virtual host configuration the following settings
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
Solution for PHP:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST,GET,OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
(Need to send that before any other content)
Set up CORS (Cross-site HTTP Requests) in node. For me it looks like the following:
app.use('/api', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
next();
});
for nginx
location / {
proxy_pass http://localhost:59100;
proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
# Simple requests
if ($request_method ~* "(GET|POST)") {
add_header "Access-Control-Allow-Origin" *;
}
# Preflighted requests
if ($request_method = OPTIONS ) {
add_header "Access-Control-Allow-Origin" *;
add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD";
add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
}
# proxy_cache_bypass $http_upgrade;
# add_header Access-Control-Allow-Origin *;
# add_header Access-Control-Allow-Headers Content-Type;
}
see
https://distinctplace.com/2017/04/17/nginx-access-control-allow-origin-cors/
I had the same problem and I solved it by adding the following header:
Access-Control-Allow-Headers: content-type
To me with PHP, localy works even if i set only this header setting:
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');

Resources