ERPNext Foundation ERPNext Cloud Chat Blog Discuss Frappé* Donate

Enabling CORS on Frappe to allow insecure HTTP endpoints


#1

We are trying to query an API from within Frappe desk. However the API is served over HTTP and not HTTPS so we are getting an insecure content warning preventing the API call.

I searched the forum and came across several posts and solution approaches on how to do this, however nothing is comprehensive and explains how to dot it right and how to troubleshoot.

I am sharing my approach with the hope that someone can help me and so we can create a comprehensive guide.

This is what I did:

  1. Confirming that current nginx config is OK by just restarting nginx
sudo service nginx restart
  1. Testing nginx config and looks OK, however it looks at /etc/nginx/nginx.conf while we are supposed to modify frappe-bench/config/nginx.conf
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
  1. Opening nginx.conf within frappe config folder
sudo vim config/nginx.conf
  1. Replacing old part of nginix.conf
        location @webserver {

                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Frappe-Site-Name $host;
                proxy_set_header Host $host;
                proxy_set_header X-Use-X-Accel-Redirect True;
                proxy_read_timeout 120;
                proxy_redirect off;

                proxy_pass  http://frappe-bench-frappe;
        }

With new snipped according to https://gist.github.com/revant/4baf8c4dadc9b6b28ff3d85bd049c066

Attention, I replaced site1.local.com in line 28 with $host as this is how my config was and we are using DNS based multitenancy.

location @webserver {
        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, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
                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' 'Authorization,DNT,X-Mx-ReqToken,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' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        }
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Frappe-Site-Name $host;
        proxy_set_header Host $host;
        proxy_set_header X-Use-X-Accel-Redirect True;
        proxy_read_timeout 120;
        proxy_redirect off;

        proxy_pass  http://frappe-bench-frappe;
}
  1. Saving and restarting nginx
sudo service nginx restart
  1. Testing if CORS enabled –> no

My function causing a CORS request is still throwing an error in the console

Mixed Content: The page at 'https://xxxx/desk#Form/Batch/495520D' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://192.168.100.49:2021/PrintBatchLabel'. This request has been blocked; the content must be served over HTTPS.

(Note: domain replaced by xxxx for privacy)

  1. Testing nginx.config
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

So as you can see I am stuck, I dont have an error but at the same time I dont have the ability to call an insecure API endpoint.

What am I doing wrong and how can I do it right?


#2

I did the following:
======if need to allow cross origin requests====Add following to /etc/nginx/conf.d/erpnext.con location @webserver block for each site
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, OPTIONS, PUT';
            add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
            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, PUT';
            add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,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, PUT';
            add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
    }

    if ($request_method = 'PUT') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
            add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
    }

======


#3

I don’t think the issue is related to CORS.

It must be related to Mixed Content - https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content

What can be done :