18

I have a web-app with an AngularJS front-end and a Web Api 2 back-end, and it uses bearer-tokens for authentication.

All is well in FireFox & IE, but with Chrome, my initial login request is SOMETIMES pre-flighted.

Here's the call from the AngularJS service:

$http.post(http://localhost:55483/token, data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) { ... });

The preflight request gets kicked back with an "Allow-Access-Control-Origin" error.

However, if I click the Login button again (thereby re-sending the above request) all is well.

Any idea on how to prevent/trap/handle this?

PS: I use the LOC

context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

in the ApplicationOAuthProvider.cs file to put the CORS allow-header on the /Token request, which works fine in IE, FireFox and sometimes in Chrome.

AD.Net
  • 13,352
  • 2
  • 28
  • 47
FancyNancy
  • 236
  • 1
  • 2
  • 6
  • Did you add `allowcors` in the startup for `webapi`? – AD.Net Nov 17 '14 at 19:35
  • Do you mean this LOC: app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); I tried to put that in but the compiler says: Owin.IAppBuilder' does not contain a definition for 'UseCors' – FancyNancy Nov 17 '14 at 19:48
  • Yes, it looks similar, but you might need to include some nuget package for cors – AD.Net Nov 17 '14 at 19:51
  • Got the Owin.Cors NuGet package, added in the AllowAll thing - still same problem. That 'AllowAll' seems to only apply to the Web Api controllers, and not to the /Token route. – FancyNancy Nov 17 '14 at 20:21
  • 23
    Figured this out with help from post by LeftyX on Jun 29: Move this LOC app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); to the FIRST LINE in the ConfigureAuth method of Startup.Auth.cs. Then, REMOVE this LOC context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); from the GrantResourceOwnerCredentials() method of ApplicationOAuthProvide.cs. Preflight CORS-request them gets handled properly, and then the actual requet goes through. – FancyNancy Nov 18 '14 at 13:24
  • 1
    @FancyNancy Thank you FancyNancy for your comment! Can you make your comment an answer to this question? Your comment was the only answer that worked for me! I'm sure someone else would appreciate a specified answer. – Nathan Yeung Apr 03 '15 at 18:36

4 Answers4

17

The below is Fancy comment:

Figured this out with help from post by LeftyX on Jun 29:
- Move this LOC app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); to the FIRST LINE in the ConfigureAuth method of Startup.Auth.cs.
- Then, REMOVE this LOC context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); from the GrantResourceOwnerCredentials() method of ApplicationOAuthProvide.cs.

Preflight CORS-request them gets handled properly, and then the actual requet goes through


Thank man, you save my whole day.
Cause it happens for many guys, I bring your comment to answer box for other guys can see it.

I don't want to get vote up for this. Please comment on my answer instead

Thank you

Steve Lam
  • 979
  • 1
  • 17
  • 40
  • 2
    Thanks for posting this answer from Fancy, this was the issue on my case, I was setting cors option in multiple places. – mini998 Dec 08 '16 at 00:30
  • 1
    At step 2, you can rewrite header by using `context.OwinContext.Response.Headers.SetValues("Access-Control-Allow-Origin", allowedOriginStr);` – Vunb Jul 19 '17 at 03:58
4

I hope this is able to help somebody out there. For me:

  • adding the app.useCors(); LOC did not work.
  • Adding the app.useCors(); LOC worked for other people on my team.

So I needed a solution that would work across everyone's environments.

Ultimately what I ended up doing was adding the header and value right into the Web.config with the following (where localhost:9000 is my node application that is serving up angular):

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="http://localhost:9000" />
        <add name="Access-Control-Allow-Headers" value="Content-Type"/>
      </customHeaders>
    </httpProtocol>
  </system.webServer>

Then in production you can just change the origin value to the production front-end url.

If you want CORS enabled for all origins, change the value to "*".

James
  • 624
  • 4
  • 13
2

By default - Access-Control-Max-Age: seconds is 0 and your requests not caching.

Try set it to max value: (Owin selfhost). It solve problem with extra OPTIONS requests

            app.UseCors(new CorsOptions
            {
                PolicyProvider = new CorsPolicyProvider
                {
                    PolicyResolver = context => Task.FromResult(new CorsPolicy
                    {
                        AllowAnyHeader = true,
                        AllowAnyMethod = true,
                        AllowAnyOrigin = true,
                        SupportsCredentials = false,
                        PreflightMaxAge = Int32.MaxValue // << ---- THIS
                    })
                }
            });
ZOXEXIVO
  • 920
  • 9
  • 21
0

Let me add one thing I have learned today. This sample:

app.UseCors(CorsOptions.AllowAll);

worked for me since the beginning. I just wasn't aware, becuase the requests I have been doing to verify, did not have following headers:

Origin: http://hostname
Access-Control-Request-Method: GET

Only after I added those, the correct headers started to appear in responses.

h3rb4l
  • 73
  • 6