53

I am running a local webserver, which runs an XHR request to an ngrok server, also run from my PC.

I'm getting XMLHttpRequest cannot load http://foo.ngrok.io/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

It appears the ngrok FAQ mentions CORS headers, but only in relation to basic auth - it doesn't mention how to set the headers so I could test my app in development.

How do I change ngrok's CORS options to allow loading requests from localhost?

UPDATE: different use case. BOUNTY FOR THIS SOLUTION:

I am getting the following error:

login.php:1 Access to XMLHttpRequest at 'http://localhost/lagin/public/login.php'
from  origin 'http://062b-96-230-240-153.ngrok.io' has been blocked by CORS 
policy: The request client is not a secure context and the resource is in more- 
private address space `local`. 

I've looked at Configure ngrok's CORS headers but still not sure how to proceed. When I tried ngrok http -host-header=rewrite 80 it says header not defined.

I've looked at 10 or 12 youtube videos and they all do a great job explaining what CORS is but an awful job explaining how to fix it.

I'm running virtualbox on a windows 10 machine and create a linux virtual machine. On the linux side I am running xampp as a local server.

I am happy to provide more details but I just don't know what additional information is needed.

I am able to see the login page of my site on ngrok but as soon as I make a axios call I get the above error.

Also, I tried //flags/#block-insecure-private-network-requests in chrome and set to disable. When I do that I no longer get the error but the site doesn't work.

ADDITIONAL INFORMATION:

I spoke to ngrok and they say: ...it sounds like your app is trying to call localhost somewhere in a ajax request. You will need to adjust that call to ensure it is being routed through ngrok.

here's what I'm doing:

responseData = sendData2('http://localhost/lagin/public/login.php',emailPass);

and here’s sendData2 (just for completeness)

function sendData2(url,emailPass){

    let bodyFormData = new FormData()
    for (const [key, value] of Object.entries(emailPass)) {
       //console.log(key,value)
       bodyFormData.append(key,value)
    }

    return axios({
            method: 'POST',
            url: url,
            data: bodyFormData,
            headers: {'Content-Type': 'multipart/form-data'}
            })
                .then(function(response){
                    return response.data
                })
                .catch(function(response){
                    return response
                })
}

UPDATE: Each time we tunnel into ngrok we get an address like https://2634-96-230-240-153.ngrok.io If we change the send2() call to

sendData2('http://96-230-240-153.ngrok.io/lagin/public/login.php',emailPass);

it works but this requires I change the code each time I have a new tunnel. Would adjusting the CORS policy get around this problem?

DCR
  • 14,737
  • 12
  • 52
  • 115
wildeyes
  • 6,767
  • 5
  • 19
  • 37

8 Answers8

49

I just stumbled across this issue today and was able to resolve it by starting ngrok and including the --host-header flag.

ngrok http --host-header=rewrite 3000

From the docs:

Use the --host-header switch to rewrite incoming HTTP requests.

If rewrite is specified, the Host header will be rewritten to match the hostname portion of the forwarding address.

Dave Kiss
  • 10,289
  • 11
  • 53
  • 75
  • this is to start the server or client? – Venkataramanan Jun 29 '22 at 07:37
  • 10
    With latest ngrok the option is `--host-header=rewrite` – HarlemSquirrel Aug 09 '22 at 16:12
  • 3
    Noting this here because it gave me a hard time: _not_ setting the `ngrok-skip-browser-warning` can cause issues that appear to be CORS issues specifically on GETs (pre-flight OPTIONS requests will succeed but ngrok returns a browser warning page in response to the GET, which, of course, is not what you want and doesn't include the `Access-Control-Allow-Origin` header – mway Sep 07 '22 at 18:08
8

For me, in addition to setting up the server, you also need to add to the header on each request sent from the client side
"ngrok-skip-browser-warning": true

Hai Quan Le
  • 396
  • 6
  • 11
  • 2
    If your server's CORS settings were right, but still see CORS error, that may due to ngrok. When we first time send the request through ngrok, it'll redirect to a browser warning page. So, if you turn off the browser's CORS, and print the API response, you'll see the warning page's HTML. The CORS comes from this page, not your server. Just send a header to skip this page, everything will be OK. – allenyllee Nov 17 '22 at 04:20
6

First of all ngrok is just a tunnel and not a server so configuring CORS header in ngrok is not at all possible. So any kind of CORS configuration needs to be done at the server level.

For example if you are using a nginx server, you need to configure header in the nginx conf file like:

location / {
    /*some default configuration here*/
    add_header 'Access-Control-Allow-Origin' '*';
}

By adding this header, you say that cross origin access to your address is allowed from any address as the value of the header is '*'. You can also specify a particular address for which the access to your address is allowed by replacing the value.

  • 4
    This doesn't seem correct, in my experience. I have CORS headers enabled in a Django app and when I test it with a CORS tester, it passes the test. However, when I start an ngrok tunnel to my computer and run the same CORS test through that, it fails. – Mr. Lance E Sloan Aug 22 '22 at 11:49
1

With Webpack / react, I used the 'requestly' Chrome extension and set up a rule from the Bypass CORS template. Note that after selecting Templates > Bypass CORS, you need to click Create Rule in the top right of the dialog. Then fill in the section at the top, "If domain contains <your domain" and make any other configuration changes, then you can save your rule.

enter image description here

enter image description here

Little Brain
  • 2,647
  • 1
  • 30
  • 54
  • I already use Requestly and it is indeed powerful. I can see Modify Headers option but not the 'Bypass CORS template' option. Can you please help me with appropriate steps / screenshots? – Mukul Gupta Sep 12 '22 at 09:02
1

you should add this to you headers then 100% worked: headers: { Origin: window.location.origin, },

1

For folks that are using Django with django-cors-headers, be sure to add the header to the allowed list, as I spent too much time working on this. This applies to other frameworks of course if they restrict the headers

CORS_ALLOW_HEADERS = (
    "accept",
    "authorization",
    "content-type",
    "user-agent",
    "x-csrftoken",
    "x-requested-with",
    "ngrok-skip-browser-warning"  
)
konsalex
  • 425
  • 5
  • 15
0

If you are using ngrok with nodejs/express.js .

Use this code:

app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "YOUR-DOMAIN.TLD"); // update to match 
the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content- 
Type, Accept");
next();
});

Replace "YOUR-DOMAIN.TLD" with "*" to give access to all urls OR your specific website url.

Refer to https://enable-cors.org/server_expressjs.html for more details

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Daniel Sogbey
  • 163
  • 1
  • 11
-1

Getting ngrok to work took a little time to figure out but it's actually quite easy.

In chrome there is an option to turn off CORS.  In the chrome address bar go to
chrome://flags and look for Block insecure private network requests.
This needs to be disabled.

Second, in my ajax request I had used an absolute path and this needed to be changed 
to a relative path.  

REMEMBER:This is for running localhost and exposing it to the web

DCR
  • 14,737
  • 12
  • 52
  • 115
  • Always avoid disabling CORS protection in the browser. – Mr. Lance E Sloan Aug 22 '22 at 11:50
  • Why, how else do you solve the problem? Since we are doing this on a localhost what’s the issue? – DCR Aug 22 '22 at 14:49
  • 1
    Maybe for you, personally, as an experienced developer, it's OK. You choose to take the risk. I highly recommend against suggesting it to others, though. It's too easy to forget that an important browser safety measure has been disabled. For most people, if they're tempted to turn off the browser's CORS protection, I'd tell them that it's a sign their app needs to send CORS headers. It's usually easy to implement. See the other answers to this question. – Mr. Lance E Sloan Aug 23 '22 at 12:02