Getting 'The 'Access-Control-Allow-Origin' header contains multiple values' with MEAN and nginx - node.js

I have developed an application in MEAN stack and used Nginx for HTTPS.
I have used socket.io and developed rest apis in node.
Below is my Nginx configuration;
server {
# Enable HTTP/2
listen 443 ssl;
listen [::]:443 ssl http2;
server_name api.some.com www.api.some.com;
# Use the Let’s Encrypt certificates
ssl_certificate /etc/letsencrypt/live/api.some.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.some.com/privkey.pem;
# Include the SSL configuration from cipherli.st
include snippets/ssl-params.conf;
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
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,Content-Range,Range,from,x-auth,Access-Control-Allow-Origin';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
add_header 'Cache-Control' 'no-cache';
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,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,from,x-auth,Access-Control-Allow-Origin';
add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,from,x-auth,Access-Control-Allow-Origin';
add_header 'Cache-Control' 'no-cache';
}
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,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,from,x-auth';
add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,from,x-auth';
add_header 'Cache-Control' 'no-cache';
}
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:5000/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
##### changes for socket.io
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
I am getting "The 'Access-Control-Allow-Origin' header contains multiple values" error when my application is attempting to connect socket.
I have found a workout. If I comment the 'add_header' part from the GET section and add the 'Access-Control-Allow-Origin' header from my code then it is working fine. If I don't add the header in my code then the GET rest apis are not working , its asking for the 'Access-Control-Allow-Origin' header.
But I don't want to do that as nginx should handle this, my code should not bother about these headers.
What am I missing?
UPDATE :
I added 'Access-Control-Allow-Origin' in allow headers part of the GET in nginx and removed the GET specific code from node server , the get rest APIs started working BUT the socket started throwing CORS origin error.

Related

Nodejs reverse proxy for static files not working with nginx

I'm trying to setup Angular + Nodejs behind Ngnix on Ubuntu.
Everything is working fine for Angular and Nodejs API but I'm not able to serve static files.
Here is my configuration (/etc/nginx/sites-enabled/default):
location / {
# First attempt to serve request as file, then as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://localhost:7777;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
# preflight requests
if ( $request_method = OPTIONS ) {
add_header "Access-Control-Allow-Origin" *;
add_header "Access-Control-Allow-Credentials" true;
add_header "Access-Control-Allow-Methods" "GET, POST, PUT, HEAD, DELETE, OPTIONS";
add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
return 200;
}
}
location /static {
proxy_pass http://localhost:7777;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
The /api route works fine but /static doesn't.
On local, /static works fine because there is no nginx.
I have following directory structure to serve static files:
public
static
images
css
fonts
https://somewebsite.com/api/read (works fine)
https://localhost:3000/static/images/test.png (works fine)
https://somewebsite.com/static/images/test.png
is not working. What am I doing wrong?
https://localhost:3000/static/images/test.png (works fine) and https://somewebsite.com/static/images/test.png is as expected. According to your configuration, you are also redirecting /static to port 7777: proxy_pass http://localhost:7777;
Changing:
proxy_pass http://localhost:7777;
to:
proxy_pass http://localhost:3000;
should do the trick
I fixed this with following entry:
location /static/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_pass "http://localhost:7777/static/";
# preflight requests
if ( $request_method = OPTIONS ) {
add_header "Access-Control-Allow-Origin" *;
add_header "Access-Control-Allow-Credentials" true;
add_header "Access-Control-Allow-Methods" "GET, POST, PUT, HEAD, DELETE, OPTIONS";
add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
return 200;
}
}

i can't enable CORS in nginx

I can't Enable CORS on my API Gateway instance, this is how it looks:
Everything is installed on an nginx server under ubuntu 20.04.
React Font-end: https://example.com
-nginx
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /home/ubuntu/front;
index index.html index.htm;
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
expires -1;
# access_log logs/static.log; # I don't usually include a static log
}
location ~* \.(?:css|js)$ {
try_files $uri =404;
expires 1y;
access_log off;
add_header Cache-Control "public";
}
# Any route containing a file extension (e.g. /devicesfile.js)
location ~ ^.+\..+$ {
try_files $uri =404;
}
# Any route that doesn't have a file extension (e.g. /devices)
location / {
try_files $uri $uri/ /index.html;
}
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl; # managed by Certbot
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/xxx.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/xxx.com/privkey.pem; # managed by Certbot
server_name example.com www.example.com;
root /home/ubuntu/front;
index index.html index.htm;
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
expires -1;
# access_log logs/static.log; # I don't usually include a static log
}
location ~* \.(?:css|js)$ {
try_files $uri =404;
expires 1y;
access_log off;
add_header Cache-Control "public";
}
# Any route containing a file extension (e.g. /devicesfile.js)
location ~ ^.+\..+$ {
try_files $uri =404;
}
# Any route that doesn't have a file extension (e.g. /devices)
location / {
try_files $uri $uri/ /index.html;
}
}
express Back-end: https://api.mydomain.com
code add to js
app.use(cors());
´
- nginx
upstream api {
server xx.xx.xx.xx;
}
server {
server_name api.mydomain.com;
location / {
proxy_pass http://127.0.0.1:4001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_connect_timeout 30;
proxy_send_timeout 30;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/xx.xxxx.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/livexx.xxxx.com/privkey.pem; # managed by Certbot
}
minio objectstorage: https://minio.example.com
server {
listen 443 ssl;
server_name minio.example.com;
ssl_certificate /etc/minio/certs/public.crt;
ssl_certificate_key /etc/minio/certs/private.key;
# To allow special characters in headers
ignore_invalid_headers off;
# Allow any size file to be uploaded.
# Set to a value such as 1000m; to restrict file size to a specific value
client_max_body_size 1000m;
# To disable buffering
proxy_buffering off;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_connect_timeout 300;
# Default is HTTP/1, keepalive is only enabled in HTTP/1.1
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
proxy_pass https://localhost:9000;
# Ajouter les headers de contrôle d'accès CORS
#add_header 'Access-Control-Allow-Origin' '*' always;
#add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
#add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept' always;
#add_header 'Access-Control-Allow-Credentials' 'true' always;
}
i can manage to make http requests from example.com to api.example.com without having cors errors
but when i do an http request fomr example.com to api.example.com then from api.example.com to mini.example.com(or any api), i have cors error " Access to xmlhttprequest at https://api.example.com/upload from https://example.com has been blocked by cors policy: no 'access-control-allow-origin' header is present on the requested ressource
proxy_set_header Access-Control-Allow-Origin "*";
sovled the issue

Error: Request failed with status code 405 , payload return HTML not JSON like intended

I'm setting up a webapps using Node JS + React + NGINX on AWS
and then when i want to access the url /auth
it return me some HTML code instead of JSON like i wanted to be
i tested the code on LOCALHOST and it works fine
I tried to set the folder permission, because i think maybe user permission is the problem
I also tried editing some stuff on the Nginx.conf
below is my app.conf for the nginx
upstream webapp{
server 127.0.0.1:3018;
}
server_names_hash_bucket_size 64;
server_names_hash_max_size 512;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name 127.0.0.1;
server_name_in_redirect off;
if ($http_x_forwarded_proto = 'http'){
return 301 https://$host$request_uri;
}
location / {
root /home/website/client/build;
try_files $uri /index.html;
log_not_found off;
access_log off;
}
#error_page 405 =200 $uri;
if ( $http_user_agent ~* (nmap|nikto|wikto|sf|sqlmap|bsqlbf|w3af|acunetix|havij|appscan) ) {
return 403;
}
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block;";
add_header Strict-Transport-Security "max-age=2592000; includeSubDomains" always;
}
action {…}
​
payload: Object { isAuth: false, error: true }
​
type: "auth_member"
i expect the output code like this one
but instead the web give me something else
you have to define the upstrem location to be proxed to:
# this is an example you can modify the path on as you get it
location /api {
proxy_pass http://webapp;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}

How to enable CORS in Nginx proxy server?

As my title, here is the config file located in conf.d/api-server.conf
server {
listen 80;
server_name api.localhost;
location / {
add_header 'Access-Control-Allow-Origin' 'http://api.localhost';
add_header 'Access-Control-Allow_Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_redirect off;
proxy_set_header host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-forward-for $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3000;
}
}
The nginx.conf file stay the same as default.
After I send request to api.localhost (api.localhost/admin/login), I still receive 405 error:
XMLHttpRequest cannot load http://api.localhost/admin/login. Response
to preflight request doesn't pass access control check: No 'Access-
Control-Allow-Origin' header is present on the requested resource.
Origin 'http://admin.localhost:3000' is therefore not allowed access.
The response had HTTP status code 405.
The issue is that your if condition is not going to send the headers in the parent in /. If you check the preflight response headers it would be
HTTP/1.1 204 No Content
Server: nginx/1.13.3
Date: Fri, 01 Sep 2017 05:24:04 GMT
Connection: keep-alive
Access-Control-Max-Age: 1728000
Content-Type: text/plain charset=UTF-8
Content-Length: 0
And that doesn't give anything. So two possible fixes for you. Copy the add_header inside if block also
server {
listen 80;
server_name api.localhost;
location / {
add_header 'Access-Control-Allow-Origin' 'http://api.localhost';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'http://api.localhost';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_redirect off;
proxy_set_header host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-forward-for $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3000;
}
}
Or you can move it outside the location block, so every request has the response
server {
listen 80;
server_name api.localhost;
add_header 'Access-Control-Allow-Origin' 'http://api.localhost';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_redirect off;
proxy_set_header host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-forward-for $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3000;
}
}
If you only want to allow certain locations in your config for CORS. like /api then you should create a template conf with your headers
add_header 'Access-Control-Allow-Origin' 'http://api.localhost';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
and then use
include conf.d/corsheaders.conf;
in your OPTIONS block and /api block. So CORS are only allowed for the /api. If you don't care which location for CORS then you can use the second approach of moving core headers to server block

What MongoDB user role can make POST calls?

I just have created a MongoDB instance on Ubuntu 14.04, with authentication by username:password.
The user I've created is like this:
{
"_id" : "myDatabase.myUser",
"user" : "myUser",
"db" : "myDatabase",
"roles" : [ { "role" : "readWrite", "db" : "myDatabase" } ]
}
And the URI String that I use on my REST API written in Node.js (with Express and Mongoose) is like:
mongodb://myUser:password#localhost:27017/myDatabase
The Connection is OK and the GET methods works fine, but when I use a POST method, like a signup by email/password, the response is:
Status Code:405 Not Allowed
Any idea? Thanks in advance!
FYI: I'm using Nginx as reverse proxy and Web Server for the Frontend (AngularJS app), and the config is:
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/nginx.access.log;
error_log /var/log/nginx/nginx.error.log;
location / {
expires -1;
add_header Pragma "no-cache";
add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";
root /usr/share/www;
try_files $uri $uri/ /index.html =404;
}
location /api/v1 {
proxy_set_header "Access-Control-Allow-Origin";
proxy_set_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, PUT, DELETE";
proxy_set_header "Access-Control-Allow-Headers" "X-Requested-With,Accept,Content-Type, Origin";
proxy_pass http://127.0.0.1:3000/api/v1;
proxy_buffering on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header origin "http://example.com";
}
}
I think that it isn't a mongodb restriction. Mongo can't know if the request is POST or GET. Have you verified if the request arrives at nodejs server? I think that nginx is who returns the 405 status code.
It's possible that the failure is due to try to return a static page as response to the POST request. Try adding into nginx.conf file:
# To dispatch static pages on POST request
error_page 405 = 200 $uri;
I have added the following and nginx at least works!:
proxy_redirect off;
The nginx config for default now is:
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/nginx.access.log;
error_log /var/log/nginx/nginx.error.log;
location / {
expires -1;
add_header Pragma "no-cache";
add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";
root /usr/share/www;
try_files $uri $uri/ /index.html =404;
}
location /api/v1 {
proxy_set_header 'Access-Control-Allow-Origin' 'http:/example.com';
proxy_set_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
proxy_set_header 'Access-Control-Allow-Headers' 'X-Requested-With,Accept,Content-Type, Origin';
proxy_pass http://127.0.0.1:3000/api/v1;
proxy_redirect off;
proxy_buffering on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header origin "http://example.com";
}
}
I hope this be valid for somebody.

Resources