2014-10-28 2 views
9

Я использую маркер аутентификации для небольшого проекта на основе этой статьи: http://bitoftech.net/2014/06/09/angularjs-token-authentication-using-asp-net-web-api-2-owin-asp-net-identity/Owin маркер аутентификации 400 Bad Request ОПЦИИ из браузера

Все, кажется, работает нормально, за исключением одной вещи: маркер аутентификации на основе Owin не позволяет запрос OPTIONS on/token endpoint. 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; 

    }; 

ответ

-3

решаемой его. Проблема не была отправлена ​​с заголовком запроса OPTIONS. Access-Control-Request-Method

+2

собирался ответить, но вы решили ее, рад, что мой учебник и примеры кода полезны :) –

+2

же проблема здесь. И я до сих пор не понял, как это решить. – otaviosoares

+2

Мне было бы хорошо, если бы вы подробно остановились на том, как вы решили проблему. Я решил это, используя решение, созданное @knr – Aziz

31

Я потерял некоторое время на этой проблеме сегодня. Наконец, я думаю, что нашел решение.

Переопределить метод внутри 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); 
} 

Это, как представляется, сделать три необходимые вещи: сервер аутентификации

  • Force в ответ на OPTIONS запрос с 200 (OK) HTTP статуса,
  • Разрешить запрашивать откуда угодно, установив Access-Control-Allow-Origin
  • Позволяет задать заголовок Authorization на подзапросе uent, задав Access-Control-Allow-Headers

После того, как эти шаги углы, наконец, корректно ведут себя при запросе конечной точки маркера с помощью метода OPTIONS. Состояние OK возвращается и повторяет запрос с методом POST для получения полных данных токена.

+0

Спасибо @knr, ваше решение отлично работает для меня. Я также добавляю заголовок «Разрешить» в ответе, предоставляя список HTTP-глаголов, допущенных для ресурсов: context.OwinContext.Response.Headers.Add («Разрешить», новый [] {«GET, POST, PUT , DELETE, HEAD "}); –

+0

спасибо @knr, ваше решение отлично работает и для меня. –

-4

Это должно сделать трюк:

app.UseCors(CorsOptions.AllowAll); 
+2

Пожалуйста, объясните немного, чтобы другие пользователи могли понять причину проблемы и как работает решение. Благодаря :) –