Asp.net

OWIN 令牌身份驗證 400 來自瀏覽器的 OPTIONS 錯誤請求

  • October 29, 2018

我正在根據這篇文章對小型項目使用令牌身份驗證:http: //bitoftech.net/2014/06/09/angularjs-token-authentication-using-asp-net-web-api-2-owin-asp-net -身份/

除了一件事之外,一切似乎都執行良好:基於 OWIN 的令牌身份驗證不允許在 /token 端點上進行 OPTIONS 請求。Web API 返回 400 Bad Request 並且整個瀏覽器應用程序停止發送 POST 請求以獲取令牌。

我在應用程序中啟用了所有 CORS,就像在範例項目中一樣。下面是一些可能相關的程式碼:

public class Startup
   {
       public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }

       public void Configuration(IAppBuilder app)
       {
           AreaRegistration.RegisterAllAreas();
           UnityConfig.RegisterComponents();
           GlobalConfiguration.Configure(WebApiConfig.Register);
           FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
           RouteConfig.RegisterRoutes(RouteTable.Routes);
           BundleConfig.RegisterBundles(BundleTable.Bundles);

           HttpConfiguration config = new HttpConfiguration();

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

           ConfigureOAuth(app);

           WebApiConfig.Register(config);

           app.UseWebApi(config);

           Database.SetInitializer(new ApplicationContext.Initializer());
       }

       public void ConfigureOAuth(IAppBuilder app)
       {
           //use a cookie to temporarily store information about a user logging in with a third party login provider
           app.UseExternalSignInCookie(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ExternalCookie);
           OAuthBearerOptions = new OAuthBearerAuthenticationOptions();

           OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
           {
               AllowInsecureHttp = true,
               TokenEndpointPath = new PathString("/token"),
               AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60),
               Provider = new SimpleAuthorizationServerProvider(),
               RefreshTokenProvider = new SimpleRefreshTokenProvider()
           };

           // Token Generation
           app.UseOAuthAuthorizationServer(OAuthServerOptions);
           app.UseOAuthBearerAuthentication(OAuthBearerOptions);
       }
   }

下面是我的 javascript 登錄功能(為此我使用 angularjs)

var _login = function (loginData) {

       var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;

       data = data + "&client_id=" + ngAuthSettings.clientId;

       var deferred = $q.defer();

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

       localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName, refreshToken: response.refresh_token, useRefreshTokens: true });
       _authentication.isAuth = true;
       _authentication.userName = loginData.userName;
       _authentication.useRefreshTokens = loginData.useRefreshTokens;

       deferred.resolve(response);

       }).error(function (err, status) {
           _logOut();
           deferred.reject(err);
       });

       return deferred.promise;
   };

   var _logOut = function () {

       localStorageService.remove('authorizationData');

       _authentication.isAuth = false;
       _authentication.userName = "";
       _authentication.useRefreshTokens = false;

   };

我今天在這個問題上浪費了一些時間。最後我想我找到了解決方案。

覆蓋 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);
}

這似乎做了三件必要的事情:

  • 強制身份驗證伺服器以 200 (OK) HTTP 狀態響應 OPTIONS 請求,
  • 通過設置允許來自任何地方的請求Access-Control-Allow-Origin
  • 允許Authorization通過設置在後續請求上設置標頭Access-Control-Allow-Headers

在這些步驟之後,當使用 OPTIONS 方法請求令牌端點時,角度最終表現正確。返回 OK 狀態,並使用 POST 方法重複請求以獲取完整的令牌數據。

在您的內部覆蓋此方法OAuthAuthorizationServerProvider

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

引用自:https://stackoverflow.com/questions/26614771