Asp.net
OWIN 令牌身份驗證 400 來自瀏覽器的 OPTIONS 錯誤請求
我正在根據這篇文章對小型項目使用令牌身份驗證: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(); }