简体   繁体   中英

Asp.net web api oauth cors results in 400 bad request

Following is the code. When I make an separate request using postman to "/token" it works. But when I call from a client side code, it fails with 400 bad request. When I debug I can see that the "GrantResourceOwnerCredentials" method is not getting hit. Any idea?

Client Code

return this.$http({
            url: this.config.remoteUri.account.login,
            method: "POST",
            data: { UserName: user.name, Password: user.password, grant_type: "password" },
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        }).success(function (data, status, headers, config) {
            // $scope.persons = data; // assign  $scope.persons here as promise is resolved here 
        }).error(function (data, status, headers, config) {
            //  $scope.status = status;
        });

Startup.cs

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

        public void ConfigureOAuth(IAppBuilder app)
        {
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
            OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/token"),                
                AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(20),
                Provider = new ActiveDirectoryAuthorizationProvider()
            };
            // Token Generation
            app.UseOAuthAuthorizationServer(OAuthServerOptions);

        }
    }

Webapi Config

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
        jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }
}

Authorization Filter

public class ActiveDirectoryAuthorizationProvider : OAuthAuthorizationServerProvider
{
    public override Task MatchEndpoint(OAuthMatchEndpointContext context)
    {
        if (context.IsTokenEndpoint && context.Request.Method == "OPTIONS")
        {
            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "authorization" });
            context.RequestCompleted();
            return Task.FromResult(0);
        }

        return base.MatchEndpoint(context);
    }

    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }

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

First things first: Origin header has to be set on your outgoing request (OPTIONS+POST)

I've seen this implementation of the filter in other threads but here is mine which is in fact working for me - local and production server:

 public override Task MatchEndpoint(OAuthMatchEndpointContext context)
    {
        if (context.IsTokenEndpoint && context.Request.Method == "OPTIONS")
        {

            if (!context.OwinContext.Response.Headers.Keys.Contains("Access-Control-Allow-Origin"))
                context.OwinContext.Response.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Origin", new[] { ConfigurationManager.AppSettings["allowedOrigin"] });

            if (!context.OwinContext.Response.Headers.Keys.Contains("Access-Control-Allow-Headers"))
                context.OwinContext.Response.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Headers", new[] { "Accept", "Content-Type", "Authorization", "Cache-Control", "Pragma", "Origin" });
            if (!context.OwinContext.Response.Headers.Keys.Contains("Access-Control-Allow-Methods"))
                context.OwinContext.Response.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Methods", new[] { "GET", "POST", "PUT", "DELETE", "OPTIONS" });
            context.MatchesTokenEndpoint();
            context.RequestCompleted();
            return Task.FromResult<object>(null);
        }

        return base.MatchEndpoint(context);
    }

If you still have issues please respond with more details. Please note that AppendCommaSeparatedValues is required for this to work under IE and Edge

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM