Binson Eldhose
Binson Eldhose

Reputation: 1013

CORS is not working in web api with OWIN authentication

In my application i am using web api with token based authentication with CORS support, but when client request for the token, an error occured due to CORS (Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at (my site name) . This can be fixed by moving the resource to the same domain or enabling CORS.)

I had configured everything required for CORS support ( i think so). here my configuration

Owin start up class

   public class Startup
    {
        public void Configuration(IAppBuilder app)
        {


            var config = new HttpConfiguration
            {
                DependencyResolver = new StructureMapWebApiDependencyResolver(container)

            };


            WebApiConfig.Register(config);  // registering web api configuration
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);  // cors for owin token pipeline
            app.UseWebApi(config);
            ConfigureOAuth(app);


        }

        public void ConfigureOAuth(IAppBuilder app)
        {
            var oAuthAuthorizationServerOptions = new OAuthAuthorizationServerOptions()
            {

                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
                Provider = new SimpleAuthorizationServerProvider()
            };
            // Token Generation
            app.UseOAuthAuthorizationServer(oAuthAuthorizationServerOptions);
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

        }
    }

And my webapi configuration

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.EnableCors();  // Corse support for Web api
            config.MapHttpAttributeRoutes(); // attribute based urls

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

        }
    }

here configuration in web.config

<system.webserver>
 <httpProtocol>
      <customHeaders>
        <!-- Adding the following custom HttpHeader will help prevent CORS from stopping the Request-->
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, DELETE" />
      </customHeaders>
    </httpProtocol>
</system.webserver>

and my request header from mozilla

Accept  application/json, text/plain, */*
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Content-Length  67
Content-Type    application/x-www-form-urlencoded; charset=UTF-8
Host    talenterp
Origin  http://192.168.1.11:85
Referer http://192.168.1.11:85/
User-Agent  Mozilla/5.0 (Windows NT 6.3; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0

The URLs of Apps are

Server app (which should support CORS)

{http://talenterp}

Token end point :

{http://talenterp/token}

Client app

{http://talentmvc:85}

NB: I already added

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

in GrantResourceOwnerCredentials() method of my AuthorizationServerProvider

Upvotes: 23

Views: 40232

Answers (5)

ven
ven

Reputation: 21

Had the same problem. In addition to the above indications (using app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll) only, and setting it up as first thing), I had to specify the following in the application Web.config file to be able to handle Option Requests:

<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>

Due to some headers that I was sending in the authentication request, an Options request is sent before the actual POST request, and it needs to return the correct 'Access-Control-Allow-Origin' header before the POST is sent.

If none of the CORS headers are returned by the options response, then the POST will not be sent at all. The added configuration enables this behaviour as well as for Trace.

As explained in this post

Upvotes: 2

Jude Opima
Jude Opima

Reputation: 11

I had this similar problem, I tried all the options above in startup.cs i added app.UseCors(CorsOptions.AllowAll); at the top and in the WebApiConfig i disabled

public static void Register(HttpConfiguration config)
{
    //var cors = new EnableCorsAttribute("*", "*", "*");
    //config.EnableCors(cors);
}

and also disabled cors in

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
}

And repeated this in reverse order and also included entries in web.config but all did not work.

When I begun asking myself why is app.UseWebApi(config); not accessible yet I have seen it work somewhere. I looked around and found out installing Install-Package Microsoft.AspNet.WebApi.OwinSelfHost fixes it.

Eventually, it fixed the whole problem, though app.UseCors(CorsOptions.AllowAll) has to be placed first in the startup.cs method. In fact without app.UseWebApi(config), I tested in postman and the end points actually didn't exist. Overall it's working pretty well for me now.

Upvotes: 1

Dado Kljuco
Dado Kljuco

Reputation: 201

OWIN and Microsoft.AspNet.WebApi.Cors are two separate libraries and each one needs separate configuration.

Disable use of CORS with OWIN:

public void Configuration(IAppBuilder app)
{
        //app.UseCors(CorsOptions.AllowAll);

Find GrantResourceOwnerCredentials method and add Access-Control-Allow-Origin to context so when it returns a call after authentication is completed that browser finds the header and accepts it.

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "http://localhost" });

Now install Microsoft.AspNet.WebApi.Cors package from Nuget to your webapi project, and add this to Register method

public static void Register(HttpConfiguration config)
{
        var cors = new EnableCorsAttribute("http://localhost, ", "accept,accesstoken,authorization,cache-control,pragma,content-type,origin", "GET,PUT,POST,DELETE,TRACE,HEAD,OPTIONS");

        config.EnableCors(cors);

This did it for me.

Upvotes: 10

Elger Mensonides
Elger Mensonides

Reputation: 7029

Be sure you've got only

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

configured, and not also the old style 'config.EnableCors()' in your Global.asax or WebApiConfig. Furthermore: place the above statement as the first one in your owin Startup class. Yes that really makes a difference, setting it later can also cause cors to not work.

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

        ... etc

Upvotes: 68

Odeyinka Olubunmi
Odeyinka Olubunmi

Reputation: 857

Especially if you are having problem with the Web API bearer token when using CORS then dont forget to put "TOKEN" in the list of your allowed methods.

Please put the code in your system.webServer of web.config, that is how i solved mine

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

Upvotes: 3

Related Questions