4

I am testing our Angular app (running at http://localhost:4200) against a local instance of our Node/Express/MongoDB-based API (which I'm running at http://localhost:3000).

One of the endpoints I'm testing is used to allow our in-house users to download a file. Now, on our actual API URL, we have our CORS policy set (see below for details) - and this is an internal office app run behind a VPN.

But when I try and test this download functionality on my local app running against a local instance of the API, I get this error message:

Access to XMLHttpRequest at 'http://localhost:3000/v0/filegenerator/download?emailDocId=47dh385686e780c18e905&apikey=9d98e41d-44e9-4bbb-ab3d-35b7df5272dc&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJDUkVXTWVtYmVyIjoiNWmNoIjoiU2MDc0ODd9.bA5B5bx4wPSSiVCS_LxTK1gifjtif8dj29sfUBHqpOg' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

A couple of questions here:

1.) Is this a generic Chrome security error message?

2.) Is there a way I can turn this off, so I can test downloading the file? Or can I only test this by hitting our actual live API?

How can I best get around this in my testing environment?

Added note: I do have a CORS extension - "Allow-Control-Allow-Origin: * 1.0.3" - installed in Chrome, and it's currently set to "Enable Cross-Origin Resource Sharing".

Also, on our backend Node/Express environment, this is our current setting:

  app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.header("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS");
    return next();
  });
Muirik
  • 6,049
  • 7
  • 58
  • 116
  • Simple way is, you have a chrome extension for cors so you can test it, but you should handle this better, extension is just a quick fix – Nemanja G May 15 '19 at 13:02
  • 3
    Saying "you should handle this better" is not helpful because it's so vague. If you're going to make that comment, please offer further detail. Also, I already have a CORS extension in Chrome, and it's set to "Enable Cross-Origin Resource Sharing". – Muirik May 15 '19 at 13:04
  • I do not know exactly what you should do, but you should handle it on the backend somewhere, I just said you can use that extension as a quick fix until you find/someone offers a fix on the backend. – Nemanja G May 15 '19 at 13:05
  • 2
    Already have the CORS Chrome extension. And I don't think there's anything you can do "on the backend" to handle this. I think it's a front-end browser issue. If not, details would be needed for me to know how to address it. – Muirik May 15 '19 at 13:07
  • I don't think it is a frontend issue, take a look at this: https://stackoverflow.com/a/55178922/5767800 . You usually allow cors on the backend, so if you have that set up correctly and still have an issue, it could be something else i guess.. – Nemanja G May 15 '19 at 13:10
  • 1
    I am on a Mac, so I closed out Chrome, opened up my Terminal and ran: `open -a Google\ Chrome --args --disable-web-security --user-data-dir`. Seemed to do the trick. – Muirik May 15 '19 at 14:13

3 Answers3

3

CORS headers are basically a way for a server to say, "I recognize these other servers as sources to send me requests, and it should be safe for the browser." If there is no header present, then only requests that originate from the same server are considered safe.

You should be able to configure your local application to add a the header to the response.

The plain text header would look like Access-Control-Allow-Origin: localhost:4200

Jonathon K
  • 339
  • 2
  • 6
  • 2
    Thanks. An actual example of what such a header would look like would be helpful. – Muirik May 15 '19 at 13:21
  • 1
    Okay, and that plain text header would go where? – Muirik May 15 '19 at 13:25
  • @Muirik are you aware of `chrome.exe --disable-web-security` ? you need to close all your chrome browser processes first, then run the command. – Stavm May 15 '19 at 13:27
  • @Muirik This is an HTTP header, how you add it to the response is usually highly dependant on what frameworks you are using for your Node server – Jonathon K May 15 '19 at 13:32
  • I am on a Mac, so I closed out Chrome, opened up my Terminal and ran: `open -a Google\ Chrome --args --disable-web-security --user-data-dir`. Seemed to do the trick. – Muirik May 15 '19 at 14:11
1

That is a general security feature in browsers. You cannot turn it off. One way to get around this is to allow your origin on the server side, by setting the Access-Control-Allow-Origin header. However, this won't work for preflight (OPTIONS) requests, if you don't handle them separately.

If that is not possible (due to 3rd party libs, services, authentication, etc...) you could set up a reverse proxy in Angular, which allows you to tunnel all of your requests. To the browser it looks like your requests are sent to the same domain (and port) as your angular application (and therefore assume to have the same origin).

Just create a proxy.conf.js in your project like so:

const path = "/proxy_path/*";
const proxy = "/proxy_path/";

const pathRewrite = {};
pathRewrite["^" + proxy.slice(0, -1)] = "";

const configs = {
    target: 'your_service_url',
    secure: false,
    changeOrigin: true,
    pathRewrite,
    logLevel: "debug"
}

const PROXY_CONFIG = {};
PROXY_CONFIG[path] = configs;

module.exports = PROXY_CONFIG;

And use ng serve --host 0.0.0.0 --disable-host-check --proxy-config <PATH_TO_PROXY_CONF> to start it.

I hope this helps!

nullchimp
  • 735
  • 4
  • 13
  • Thanks, but please see what I added above. We do have Access-Control-Allow-Origin currently set in our back-end API. – Muirik May 15 '19 at 13:16
  • 1
    I see. The preflight requests (OPTIONS) will be unaffected by the Allow-Control-Allow-Origin header. So the only option I see is to setup a proxy within Angular. I will post an example to this soon. – nullchimp May 15 '19 at 13:19
  • This is an under-appreciated answer. Creating a reverse proxy is definitely the best long-term solution in this situation. – Gyromite Jan 19 '22 at 01:34
1

For testing purposes you can use chrome's disable-web-security flag.

  • Close all your chrome windows.
  • Run chrome.exe --disable-web-security
Stavm
  • 7,833
  • 5
  • 44
  • 68
  • 2
    This approach worked for me. It varies a little depending on what machine you're on. I'm on a Mac, so I closed out Chrome, opened up my Terminal and ran: `open -a Google\ Chrome --args --disable-web-security --user-data-dir`. Worked for me. – Muirik May 15 '19 at 14:18