17

I'm using an angular2 front end and WebApi backend. The webapi is CORS enabled

var cors = new EnableCorsAttribute("*", "*", "*");
GlobalConfiguration.Configuration.EnableCors(cors);

and it works, because I have different sites (jQuery/Javascript) that use this api. But with angular2 it doesn't. I get the following message:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Maybe is something related to "preflight request" ?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Marcos
  • 231
  • 1
  • 5
  • 14
  • I read the docs for "Enabling Cross-Origin Requests in ASP.NET Web API" and you should have this header in the response. See section "How CORS Works" in this page: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#how-it-works. – Thierry Templier Feb 04 '16 at 13:58
  • 1
    ***I'm closing it, because it is just a typo per OP.*** – Win Feb 04 '16 at 17:28
  • i think this problem in server properties see: http://stackoverflow.com/questions/36825429/angular-2-no-access-control-allow-origin-header-is-present-on-the-requested – Emir Mamashov Nov 07 '16 at 12:45

10 Answers10

9

I had the same issue in my Angular2 application. The problem, as already stated, is that before every request made by the client a preflight request is sent to the server.

This kind of request have a type OPTIONS, and it's duty of the server to send back a preflight response with status 200 and headers set for accepting requests from that client.

This is my solution (with express):

// Domain you wish to allow
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');

// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');

// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'YOUR-CUSTOM-HEADERS-HERE');

// Set to true if you need the website to include cookies in  requests
res.setHeader('Access-Control-Allow-Credentials', true);

// Check if preflight request
if (req.method === 'OPTIONS') {
    res.status(200);
    res.end();
}
else {
    // Pass to next layer of middleware
    next();
}

As you can see, i set the headers and then fetch if the request type is OPTIONS. In that case i send back a status 200 and end the response.

In this way, the client will be authorized and you will be also able to set your custom headers in all the requests.

Matteo Tosi
  • 434
  • 4
  • 8
8

Your error message tells that there is no Access-Control-Allow-Origin in the response of your call. It's something necessary to enable CORS for this request. It's not something related to Angular2.

This is triggered on the client side by the adding of the Origin header in the request. Do you have this header in your request? Do you use preflighted requests in your other applications. As a reminder:

  • Simple requests. This use case applies if we use HTTP GET, HEAD and POST methods. In the case of POST methods, only content types with the following values are supported: text/plain, application/x-www-form-urlencoded and multipart/form-data.
  • Preflighted requests. When the "simple requests" use case doesn't apply, a first request (with the HTTP OPTIONS method) is made to check what can be done in the context of cross-domain requests.

Perhaps OPTIONS requests aren't correctly handled on the server side (don't return correct headers, ...).

What would be interested is to tell us on which requests the error occurs: the OPTIONS one or the target request. You can have a look at the Network tab in DevTools...

See these links for more details about how CORS works:

Hope it helps you, Thierry

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • 1
    +1 Gave me the right direction as I was struggling on the client, but the pre-flight error was because of server blockage of cors request with some headers. So have to allow all headers in my scenario. – Nexus23 May 16 '16 at 11:51
  • @Thierry Templier can you take a look on this [question](https://stackoverflow.com/questions/45444625/angular-2-httppost-to-oauth2/45444912?noredirect=1#comment77860961_45444912)? – Skizo-ozᴉʞS ツ Aug 02 '17 at 08:48
  • Great explanation. Solution was given by @"Matteo Tosi" – boctulus Jan 02 '19 at 21:24
1

Do you have any options set into your web.config file for cors ? i.e something like <add name="Access-Control-Allow-Origin" value="*"/>

If yes make sure to remove that, and control the cors through the code only.

The Answer here will help you.

Community
  • 1
  • 1
Chidilives
  • 11
  • 2
1

I know the question is not asking for PHP code. I got here because of this whole preflight thing and Angular2. When I looked at Matteo's answer, then I realized why the request to my server is coming back with 401. This because in the preflight browser does not send the Authorization token and therefore the server comes back with 401 and the browser thinks CORS is not allowed. Please be aware the code below should only be used in development server unless you know what you're doing.

In PHP you can do this:

if (strtolower($_SERVER['REQUEST_METHOD']) === 'options') {
         header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
         header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
         header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type, Authorization');
         header('Access-Control-Allow-Credentials: true');
         echo 'Allowed';
         exit;
}

OR Nginx

if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        #
        # Tell client that this pre-flight info is valid for 20 days
        #
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
     }

Remember whatever other headers you're sending to the server you must be added to Access-Control-Allow-Headers list.

Jsonras
  • 1,120
  • 13
  • 10
0

I'm working with Angular 2 for the front-end and nodeJS (Expressjs) to the API

Angular 2 is working under localhost:3000 and express is working on localhost:8000

The problem happen when localhost:3000 tries call a URL with the POST method... The expressJS server rejects the call because it comes from another server (or port)

To solve the problem you should tell node js to accept calls from the localhost:3000 server...

You can find a library (CORS) to avoid this problem in this link:

0

You can add one add-on in your Firefox browser. It will work in your firefox browser like charm. Cors Everywhere solved my problem. https://addons.mozilla.org/en-US/firefox/addon/cors-everywhere/

SUBHASIS MONDAL
  • 705
  • 9
  • 20
0

For development purpose add this Chrome extension and enable cross-origin resource sharing.

Shamsul
  • 435
  • 6
  • 15
  • 1
    Even if the extension works properly, this is a bad solution. The OP needs to set up CORS headers correctly **on his server**. – sr9yar Jun 27 '18 at 07:45
  • @sr9yar Yes, it's not a permanent solution but if you have some server dependency then you can go ahead with this chrome extension. – Shamsul Jul 06 '18 at 12:01
0

I had also hard time with cors and angular 6.

when a request to the server is not a basic request, there is preflight request asking your server if it can answer to your request.

the server respond to that request should have those headers:

Access-Control-Allow-Origin // should be your domain

Access-Control-Allow-Headers // should be Accept, Origin, any other headers you might have.

Access-Control-Allow-Method // any methods you use

those are the " * ", " * ", " * " you added as Cors Attributes to accept all but that only worked for me in dev mode when both client and server were on same machine. after i moved to production with IIS server those values did not worked anymore especially because of the headers.

so it really easy to fix and it also working for IOS instead * * * i added this to each controller:

[EnableCors(origins: "enter your domain here", headers: "authorization, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers", methods: "GET,POST", PreflightMaxAge = 600 // optional, SupportsCredentials = true // optional)]

you can read more in the article that helped me understand what i needed to do: https://msdn.microsoft.com/en-us/magazine/dn532203.aspx

Hope it helps, Tomer.

0

In my case I used Owin and had to move the following line to the beginning of the startup

public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

            ...
        }
    }
}
Sid
  • 355
  • 1
  • 5
  • 11
0

Please follow the step for CROS ISSUE fixes in WEB API:

  1. Enabling CORS required Headers in the Application. i.e. in “Application_BeginRequest” Method in “Global.asax” file for simple requests.

  2. Placing the below code in “web.config” file helped in CORS issue for preflight requests

    <system.webServer>
              <handlers>
                <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
                <remove name="OPTIONSVerbHandler" />
                <add name="ExtensionlessUrlHandler-Integrated-4.0"path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
              </handlers>
            </system.webServer>
    

Reference: https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors

Papun Sahoo
  • 407
  • 5
  • 13