How to make CORS Authentication in WebAPI 2?

asp.net Web-ApiCors

asp.net Web-Api Problem Overview


The scenario is simple, I need to log in from another server (different from the API server) to retrieve the access token.

I installed Microsoft.Owin.Cors package on the API Server. In Startup.Auth.cs file, under public void ConfigureAuth(IAppBuilder app), I added in

app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

In WebApiConfig.cs, under public static void Register(HttpConfiguration config), I added in these lines:

// Cors
var cors = new EnableCorsAttribute("*", "*", "GET, POST, OPTIONS");
config.EnableCors(cors);

What else should I change?

asp.net Web-Api Solutions


Solution 1 - asp.net Web-Api

Look at what I have found!

Add in some custom headers inside <system.webServer>.

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, DELETE" />
  </customHeaders>
</httpProtocol>

Then I can do the CORS authentication.

Solution 2 - asp.net Web-Api

I had many trial-and-errors to setup it for AngularJS-based web client.
For me, below approaches works with ASP.NET WebApi 2.2 and OAuth-based service.

  1. Install Microsoft.AspNet.WebApi.Cors nuget package.
  2. Install Microsoft.Owin.Cors nuget package.
  3. Add config.EnableCors(new EnableCorsAttribute("*", "*", "GET, POST, OPTIONS, PUT, DELETE")); to the above of WebApiConfig.Register(config); line at Startup.cs file.
  4. Add app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); to the Startup.Auth.cs file. This must be done prior to calling IAppBuilder.UseWebApi
  5. Remove any xml settings what Blaise did.

I found many setup variations and combinations at here stackoverflow or blog articles. So, Blaise's approach may or may not be wrong. It's just another settings I think.

Solution 3 - asp.net Web-Api

After many hours of searching and looking at many many different solutions to this i have managed to get this working as per the below.

There are a number of reasons this is happening. Most likely you have CORS enabled in the wrong place or it is enabled twice or not at all.

If you are using Web API and Owin Token end point then you need to remove all the references to CORS in your Web API method and add the correct owin method because web api cors will not work with Token endpoint whilst Owin cors will work for both Web API and Token auth end points so lets begin:

  1. Make sure you have the Owin Cors package installed Remove any line that you have eg.config.EnableCors(); from your WebAPIconfig.cs file

  2. Go to your startup.cs file and make sure you execute Owin Cors before any of the other configuration runs.

    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); ConfigureAuth(app);

  3. If your still having problems go to: Startup.Auth.cs and ensure you have the following in your ConfigureAuth method (you shouldnt need this if your startup.cs file is correct)

app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

Solution 4 - asp.net Web-Api

web.config

<appSettings>
  <add key="cors:Origins" value="*" />
  <add key="cors:Headers" value="*" />
  <add key="cors:Methods" value="GET, POST, OPTIONS, PUT, DELETE" />
</appSettings>
Startup.cs

var appSettings = WebConfigurationManager.AppSettings;

// If CORS settings are present in Web.config
if (!string.IsNullOrWhiteSpace(appSettings["cors:Origins"]))
{
    // Load CORS settings from Web.config
    var corsPolicy = new EnableCorsAttribute(
        appSettings["cors:Origins"],
        appSettings["cors:Headers"],
        appSettings["cors:Methods"]);

    // Enable CORS for ASP.NET Identity
    app.UseCors(new CorsOptions
    {
        PolicyProvider = new CorsPolicyProvider
        {
            PolicyResolver = request =>
                request.Path.Value == "/token" ?
                corsPolicy.GetCorsPolicyAsync(null, CancellationToken.None) :
                Task.FromResult<CorsPolicy>(null)
        }
    });

    // Enable CORS for Web API
    config.EnableCors(corsPolicy);
}

Note: app.UserCors(...) should be called before configuring ASP.NET Identity.

Source: ASP.NET Web Application Starter Kit (ASP.NET Web API, Identity, SignalR)

Solution 5 - asp.net Web-Api

To elaborate on Youngjae's answer, there's a great tutorial on setting up OWIN with Web API and enabling CORS in the process at http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/

You'll want to add the NuGet package for CORS with the command:
Install-Package Microsoft.Owin.Cors -Version 2.1.0

Then add
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

to your Configuration method in Startup.cs so it looks something like:

public void Configuration(IAppBuilder app)
{
    HttpConfiguration config = new HttpConfiguration();
    ConfigureOAuth(app);
    WebApiConfig.Register(config);
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    app.UseWebApi(config);
}

Solution 6 - asp.net Web-Api

The answer for me was found at

https://stackoverflow.com/q/26980271/4413476

Specifically, the /Token request using an implementation of OAuthAuthorizationServerProvider.GrantResourceOwnerCredentials was adding the header in again. Add the OWIN CORS stuff before any other OWIN config, and remove the header from GrantResourceOwnerCredentials, as per that link, and voila. Good luck.

Solution 7 - asp.net Web-Api

I just want to share my experience. I spent half of the day banging my head and trying to make it work. I read numerous of articles and SO questions and in the end I figured out what was wrong.

The line

app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

was not the first one in Startup class Configuration method. When I moved it to the top - everything started working magically.

And no custom headers in web.config or config.EnableCors(corsPolicy); or anything else was necessary.

Hope this will help someone to save some time.

Solution 8 - asp.net Web-Api

You can find here the multiple ways you have to enable CORS at different scopes: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Anyway I had the same issue, and by adding the headers in different ways didn't get the complete solution.

I found out that the IIS uses handlers which overrides your CORS web app config if you don't specify the opposite.

In my case, I also had to remove the usage of IIS handlers by adding the following configuration at the main Web.config of my application:

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

Be aware that this configuration may be set by default when you create a new project depending on the type of it, but if you start from scratch you probably will have to add this config.

Solution 9 - asp.net Web-Api

Adding customer Headers might not give you as much freedom in customize your security needs. It opens up all other part of the api to the world. The following code only does that for "token", and controller other part of api should be done via EableCors annotation.

public void ConfigureAuth(IAppBuilder app)
{
    //other stuff
    app.Use(async (context, next) =>
    {
        IOwinRequest req = context.Request;
        IOwinResponse res = context.Response;
        if (req.Path.StartsWithSegments(new PathString("/Token")))
        {
            var origin = req.Headers.Get("Origin");
            if (!string.IsNullOrEmpty(origin))
            {
                res.Headers.Set("Access-Control-Allow-Origin", origin);
            }
            if (req.Method == "OPTIONS")
            {
                res.StatusCode = 200;
                res.Headers.AppendCommaSeparatedValues("Access-Control-    Allow-Methods", "GET", "POST");
                res.Headers.AppendCommaSeparatedValues("Access-Control-    Allow-Headers", "authorization", "content-type");
                return;
            }
        }
        await next();
    });
    //other stuff
}

To enable Cors, follow the instruction here.

Solution 10 - asp.net Web-Api

When using OWIN middleware to handle CORS, we do not need to add headers on the WebAPIConfig or the web.config file. Yes, adding the headers on the web.config file does work when you want public access, but if you need to limit the access based on a whitelist (domains), then allowing All access is no longer what you would like to do.

With OWINS, we can handle this by implementing this handler:

OAuthAuthorizationServerProvider.MatchEndpoint

With this handler, we can detect the request method (OPTIONS, POST...) and if the request should be treated as an Authorize or Token endpoint. This is the area where logic can be added to check the Origin header (request) and validate if this domain should be allowed by adding the response header Access-Control-Allow-Origin.

string origin = context.Request.Headers.Get("Origin");
var found = IsDomainAllowed(origin);
 if (found){
      context.Response.Headers.Add("Access-Control-Allow-Origin",
                             new string[] { origin });
 }      

For more background on this, look at this link: http://www.ozkary.com/2016/04/web-api-owin-cors-handling-no-access.html

Solution 11 - asp.net Web-Api

Complete Soluction. You just need change some files, works for me.

Global.ascx

public class WebApiApplication : System.Web.HttpApplication {
    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    } }

WebApiConfig.cs

All the request has call this code.

public static class WebApiConfig {
    public static void Register(HttpConfiguration config)
    {
        EnableCrossSiteRequests(config);
        AddRoutes(config);
    }

    private static void AddRoutes(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "api/{controller}/"
        );
    }

    private static void EnableCrossSiteRequests(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute(
            origins: "*", 
            headers: "*", 
            methods: "*");
        config.EnableCors(cors);
    } }

Some Controller

Nothing to change.

Web.config

You need add handlers in you web.config

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBlaiseView Question on Stackoverflow
Solution 1 - asp.net Web-ApiBlaiseView Answer on Stackoverflow
Solution 2 - asp.net Web-ApiYoungjaeView Answer on Stackoverflow
Solution 3 - asp.net Web-ApiPiotr StulinskiView Answer on Stackoverflow
Solution 4 - asp.net Web-ApiKonstantin TarkusView Answer on Stackoverflow
Solution 5 - asp.net Web-ApiYaronView Answer on Stackoverflow
Solution 6 - asp.net Web-ApiDale HolborowView Answer on Stackoverflow
Solution 7 - asp.net Web-ApiAndrewView Answer on Stackoverflow
Solution 8 - asp.net Web-ApiSeba CervantesView Answer on Stackoverflow
Solution 9 - asp.net Web-ApiTim HongView Answer on Stackoverflow
Solution 10 - asp.net Web-ApiozkaryView Answer on Stackoverflow
Solution 11 - asp.net Web-ApiJonas RibeiroView Answer on Stackoverflow