Возврат конечной точки API "Авторизация была отклонена для этого запроса". при отправке токена

Я следил за учебником по защите веб-API с помощью OAuth в С#.

Я делаю несколько тестов, и до сих пор мне удалось получить токен доступа с /token. Я использую расширение Chrome под названием "Advanced REST Client" для его проверки.

{"access_token":"...","token_type":"bearer","expires_in":86399}

Это то, что я вернусь от /token. Все выглядит хорошо.

Мой следующий запрос к моему тестовому API-контроллеру:

namespace API.Controllers
{
    [Authorize]
    [RoutePrefix("api/Social")]
    public class SocialController : ApiController
    {
      ....


        [HttpPost]
        public IHttpActionResult Schedule(SocialPost post)
        {
            var test = HttpContext.Current.GetOwinContext().Authentication.User;

            ....
            return Ok();
        }
    }
}

Запрос является POST и имеет заголовок:

Authorization: Bearer XXXXXXXTOKEHEREXXXXXXX

Я получаю: Authorization has been denied for this request. возвращается в JSON.

Я тоже пытался сделать GET, и я получаю то, что ожидаю, что метод не поддерживается, так как я его не реализовал.

Вот мой провайдер авторизации:

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

        using (var repo = new AuthRepository())
        {
            IdentityUser user = await repo.FindUser(context.UserName, context.Password);

            if (user == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }
        }

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
        identity.AddClaim(new Claim(ClaimTypes.Role, "User"));

        context.Validated(identity); 

    }
}

Любая помощь будет отличной. Я не уверен, что это неправильный запрос или код.

изменить: Вот мой Startup.cs

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();
        WebApiConfig.Register(config);
        app.UseWebApi(config);
        ConfigureOAuth(app);
    }

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

        // Token Generation
        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    }
}

Ответы

Ответ 1

Проблема довольно проста: Изменить порядок вашего конвейера OWIN.

public void Configuration(IAppBuilder app)
{
    ConfigureOAuth(app);
    var config = new HttpConfiguration();
    WebApiConfig.Register(config);
    app.UseWebApi(config);
}

Для OWIN-конвейера вашей конфигурации достаточно важно. В вашем случае вы пытаетесь использовать обработчик веб-API перед обработчиком OAuth. Внутри него вы подтверждаете свой запрос, обнаружили, что вы защищаете действие и пытаетесь его проверить против текущего Owin.Context.User. На данный момент этого пользователя не существует, потому что его набор из токена с помощью OAuth Handler, который вызвал позже.

Ответ 2

Вы должны добавить заявку с помощью этой схемы:

http://schemas.microsoft.com/ws/2008/06/identity/claims/role

Лучше всего использовать предопределенный набор претензий:

identity.AddClaim(new Claim(ClaimTypes.Role, "User"));

Вы можете найти ClaimTypes в System.Security.Claims.

Еще одна вещь, которую вы должны учитывать, - это роли фильтров в вашем контроллере/действии:

[Authorize(Roles="User")]

Вы можете найти простое примерное приложение, автономный owin с клиентом jquery здесь.

Ответ 3

Похоже, что версия System.IdentityModel.Tokens.Jwt, которая существует совместно с другими сборками Owin, не является правильной.

Если вы используете версию Microsoft.Owin.Security.Jwt версии 2.1.0, вы должны использовать сборку "System.IdentityModel.Tokens.Jwt" версии 3.0.2.

В консоли диспетчера пакетов попробуйте:

Update-Package System.IdentityModel.Tokens.Jwt -Version 3.0.2