Can't disable same origin policy on nginx - ajax

I need to disable the same origin policy on the server. Just as a background: I have verified that everything is working by starting chrome with the disable web security flag. Everything works as expected.
Here's what I have done on the nginx side:
upstream phpfcgi {
server unix:/var/run/php5-fpm.sock; #for PHP-FPM running on UNIX socket
}
server {
listen 80;
root /var/www/yammi2;
index index.html index.php index.htm;
server_name myserver.ch;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials 'true';
add_header Access-Control-Allow-Headers 'Content-Type,accept,x-wsse,origin';
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE';
# strip app.php/ prefix if it is present
rewrite ^/app\.php/?(.*)$ /$1 permanent;
location / {
index app.php;
try_files $uri #rewriteapp;
}
location #rewriteapp {
rewrite ^(.*)$ /app.php/$1 last;
}
# pass the PHP scripts to FastCGI server from upstream phpfcgi
location ~ ^/(app|app_dev|config)\.php(/|$) {
fastcgi_pass phpfcgi;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
}
When I then do curl call: curl -I myserver.ch, I get the following result:
HTTP/1.1 302 Found
Server: nginx/1.1.19
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.3.10-1ubuntu3.9
Set-Cookie: PHPSESSID=gvcl3v533ib91l2c6v888gl9d3; path=/
cache-control: no-cache
date: Fri, 10 Jan 2014 07:01:18 GMT
location: http://myserver.ch/admin/restaurant
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type,accept,x-wsse,origin
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
so at least it seems that the headers are set correctly, yet the result when I make the ajax call:
OPTIONS http://myserver.ch/api/v1/restaurant/closest?max=50&lat=47&lon=8 500 (Internal Server Error) jquery-2.0.3.js:7845
OPTIONS http://myserver.ch/api/v1/restaurant/closest?max=50&lat=47&lon=8 Origin http://localhost is not allowed by Access-Control-Allow-Origin. jquery-2.0.3.js:7845
XMLHttpRequest cannot load http://myserver.ch/api/v1/restaurant/closest?max=50&lat=47&lon=8. Origin http://localhost is not allowed by Access-Control-Allow-Origin. overview.html:1
I'm a bit confused by the "Internal Server Error", but I figured since it works with the flag, this has to be something to do with same origin.
The server application is a symphony app. I hope I haven't missed anything. Any idea how to fix this? Or even how to debug it?
Maybe one last snipped, here is how I make the call (again, shouldn't be the issue, because with the disable security flag it works as expected):
$.ajax({
url: url,
headers: {"x-wsse": getWsseHeader()},
beforeSend: function (request) {
request.setRequestHeader("x-wsse", getWsseHeader());
},
success: function() {
},
error: function(error) {
console.log(error.statusText);
}
});

Change this line
add_header Access-Control-Allow-Origin *;
as
add_header 'Access-Control-Allow-Origin' '';

Related

Handling CORS in Nginx as a reverse proxy

We encountered a very weird behavior when using Nginx as a reverse proxy.
We have REST services that need to be used with the browser, We configured these HTTP Golang services to handle CORS using cors package.
We noticed that when the browser triggers a preflight request the request doesn't go to the backend service and instead Nginx responds with the status 405 Method Not Allowed and the request is never forwarded or proxied to the backend service at all.
To fix this issue we had to handle OPTIONS requests manually from the location directive, This is very limited as we need the liberty to update for example the allowed headers using Access-Control-Allow-Headers based on the requested route.
How can we forward any Preflight or OPTIONS request to the backend to handle?
NOTE: We are using default Nginx configurations according to the official Nginx docker image.
file: main.go
package main
import (
"net/http"
"github.com/rs/cors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World"))
})
r := cors.AllowAll().Handler(mux)
http.ListenAndServe(":3000", r)
}
file: server.conf
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
# Handling OPTIONS for this location directive.
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "$http_origin";
add_header Access-Control-Allow-Credentials 'true';
add_header Access-Control-Allow-Headers 'Authorization, Content-Type, Origin, X-Requested-With, Accept';
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE';
add_header Content-Type 'text/plain; charset=utf-8';
return 204;
}
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Original-Remote-Addr $remote_addr;
proxy_set_header X-Original-Host $host;
}
}
Related:
Handling OPTIONS request in nginx
Cross Origin preflight request in Nginx Proxy

XMLHttpRequest blocked by CORS policy annotation #CrossOrigin

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

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