Reputation: 22212
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?
Upvotes: 76
Views: 93714
Reputation: 329
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.
Upvotes: 4
Reputation: 1985
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);
}
Upvotes: 16
Reputation: 2764
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.
Upvotes: 2
Reputation: 2694
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
Upvotes: 1
Reputation: 306
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>
Upvotes: 0
Reputation: 22212
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.
Upvotes: 81
Reputation: 25050
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.
Microsoft.AspNet.WebApi.Cors
nuget package.Microsoft.Owin.Cors
nuget package.config.EnableCors(new EnableCorsAttribute("*", "*", "GET, POST, OPTIONS, PUT, DELETE"));
to the above of WebApiConfig.Register(config);
line at Startup.cs file. app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
to the Startup.Auth.cs file. This must be done prior to calling IAppBuilder.UseWebApi
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.
Upvotes: 52
Reputation: 9471
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:
Make sure you have the Owin Cors package installed Remove any line that you have eg.config.EnableCors(); from your WebAPIconfig.cs file
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);
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);
Upvotes: 35
Reputation: 412
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.
Upvotes: 9
Reputation: 580
The answer for me was found at
Web Api 2 Preflight CORS request for Bearer Token
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.
Upvotes: 9
Reputation: 38378
<appSettings>
<add key="cors:Origins" value="*" />
<add key="cors:Headers" value="*" />
<add key="cors:Methods" value="GET, POST, OPTIONS, PUT, DELETE" />
</appSettings>
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.
Upvotes: 23