Monday 1 May 2017

Node/Nginx doesn't allow cross origin for file upload on mobile

I have an app where the client makes a multipart request from example.com to api.example.com through https. Uploading a picture.

It works on a desktop machine but breaks when I try the same request from Safari on iOS giving me this error:

[Error] Origin https://example.com is not allowed by Access-Control-Allow-Origin.
[Error] Failed to load resource: Origin https://example.com is not allowed by Access-Control-Allow-Origin. (graphql, line 0)
[Error] Fetch API cannot load https://api.example.com/graphql. Origin https://example.com is not allowed by Access-Control-Allow-Origin.

I'm using the cors npm package on the API like this:

app.use(
    cors({
        origin: globalConfig.CLIENT_URI,
        credentials: true,
        allowedHeaders: ['Access-Control-Allow-Origin', 'Authorization', 'Access-Control-Allow-Headers', 'Origin', 'X-Requested-With', 'Content-Type', 'Accept']
    })
);

Since I'm using GraphQL my client uses an Apollo network interface that looks like this:

const networkInterface = createNetworkInterface({
    uri: 'example.com/graphql',
    opts: {
        credentials: 'include',
        mode: 'cors',
    }
});

All of this is going through an Nginx reverse proxy on DigitalOcean. Here this is my Nginx config:

Config at /etc/nginx/sites-enabled:

server {
        listen 80;
        listen [::]:80 default_server;
        return 301 https://$host$request_uri;
}

Individual server configs at /etc/nginx/conf.d/yupty.vladyv.me.conf, almost identical, just the addresses and names different:

 server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name example.com;

        ssl_certificate /etc/letsencrypt/live/examp/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/yupty.vladyv.me/privkey.pem;

        include snippets/ssl-params.conf;

        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:3000/;
            proxy_ssl_session_reuse off;
            proxy_set_header Host $http_host;
            proxy_cache_bypass $http_upgrade;
            proxy_redirect off;
        }
    }

I'm baffled by the fact that it works on desktop but not on a phone. After logging the origin on the failing request it gives the absolute same URL that's enabled with cors. Do you guys have any ideas?



via Vlady Veselinov

No comments:

Post a Comment