Авторизация фильтра в Web Api 2.0 с неработающими OauthBearerTokens

У меня есть одностраничное приложение (Angular Js + веб-API AspNet), использующее аутентификацию в стиле OAuthBearerToken.

Мой код выглядит следующим образом

[assembly: OwinStartupAttribute(typeof(App.Web.Startup))]
namespace App.Web
{
    public partial class Startup
    {
     public void Configuration(IAppBuilder app)
      {
        var config = new HttpConfiguration();
        config.SuppressDefaultHostAuthentication();


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


        config.Filters.Add(new ValidateModelStateAttribute());
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

        // Web API routes
        config.MapHttpAttributeRoutes();

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

        //register autofac
        var builder = new ContainerBuilder();

        builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
        builder.RegisterControllers(Assembly.GetExecutingAssembly());
        builder.RegisterFilterProvider();
        builder.RegisterModelBinderProvider();

        builder.RegisterWebApiFilterProvider(config);
        builder.RegisterWebApiModelBinders(Assembly.GetExecutingAssembly());
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());


        var container = builder.Build();
        var resolver = new AutofacWebApiDependencyResolver(container);
        config.DependencyResolver = resolver;
        app.UseAutofacMiddleware(container);
        app.UseAutofacWebApi(config);
        app.UseWebApi(config);
        ConfigureOAuth(app, container);
    }

     public void ConfigureOAuth(IAppBuilder app, IContainer container)
      {
        var oAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),

            Provider = container.Resolve(typeof(SimpleAuthorizationServerProvider)) as IOAuthAuthorizationServerProvider
        };
        app.UseOAuthBearerTokens(oAuthServerOptions);
        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    }
}

}

Моя реализация SimpleAuthorizationProvider приведена ниже.

 public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
  {

    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[] {"*"});

        var userManager = context.OwinContext.GetAutofacLifetimeScope().Resolve<IUserStore<User>>() as UserStore;
        if (userManager != null)
        {
            var user = await userManager.FindByNameAsync(context.UserName);

            if (user == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }
            var phash = await userManager.GetPasswordHashAsync(user);
            //the hash of the incoming password
            var passwordHasher = new PasswordHasher();
            var result = passwordHasher.VerifyHashedPassword(phash, context.Password);

            if (result == PasswordVerificationResult.Success)
            {
                var identity = new ClaimsIdentity(context.Options.AuthenticationType);
                identity.AddClaim(new Claim(ClaimTypes.Sid, user.Id.ToString()));
                identity.AddClaim(new Claim(ClaimTypes.Email, user.UserName));
                context.Validated(identity);
                               }
            else
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");

            }

        }
    }


}

Теперь возникает проблема, когда я отправляю запрос на публикацию в конечную точку /token. Все работает хорошо, и я получаю токен на предъявителя.

Всякий раз, когда я пытаюсь получить доступ к методу действия, аннотированному атрибутом авторизации с заголовком авторизации HTTP, установленным на носитель {access_token}, я получаю сообщение

"Авторизация этого запроса отклонена".

Пожалуйста, я делаю что-то не так?


person Seth IK    schedule 19.11.2014    source источник
comment
У меня такая же проблема. Вы когда-нибудь находили решение?   -  person abrodersen    schedule 19.03.2015


Ответы (3)


Вы должны отправить токен в заголовке авторизации, используя схему Bearer.

Я предполагаю, что вы отправляете его как часть строки запроса, поэтому ваши конечные точки, защищенные API, не понимают этого. Пожалуйста, проверьте мой подробный пост о аутентификация AngularJS с помощью веб-API, которая точно соответствует вашему сценарию.

person Taiseer Joudeh    schedule 20.11.2014

У вас есть файл WebApiConfig.cs в вашем проекте с методом Register(HttpConfiguration config) в нем?

Если да, то он должен содержать следующее:

public static void Register(HttpConfiguration config)
{      
  // Move config.SuppressDefaultHostAuthentication() from Startup::Register method to this method
  config.SuppressDefaultHostAuthentication();

  // Add a filter handling "Bearer" authentication to the known filters
  config.Filters.Add(new HostAuthenticationFilter("Bearer"));
}

У меня была та же проблема, что и у вас, и я исправил ее с помощью этого. Решение было предложено https://stackoverflow.com/a/34166821/867600.

person Christophe Cadilhac    schedule 17.05.2017

как вы передаете заголовок в своем запросе? так должно быть

Авторизация: носитель imSXTs2OqSrGWzsFQhIXziFCO3rF...

// If we already have a bearer token, set the Authorization header.
var token = sessionStorage.getItem(tokenKey);
var headers = {};
if (token) {
    headers.Authorization = 'Bearer ' + token;
}

$.ajax({
type: 'GET',
url: 'api/values/1',
headers: headers
}).done(function (data) {
self.result(data);
}).fail(showError);

см. эту ссылку. очень хорошие детали.

Надеюсь, это поможет.

person Omar.Alani    schedule 19.11.2014