ASP.NET 5 OAuthBearerAuthentication: следующая схема аутентификации не была принята: носитель

обновление:

Pinpoint помог мне получить этот прототип с пусковой площадки - я был очень близок, за исключением:

  • мне нужно обновить до beta6 СДК в эти инструкции. Глобальный.json теперь выглядит следующим образом:
{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.0-beta6"
  }
}
  • я обновил ссылки в проекте.в JSON:
{
  "webroot": "wwwroot",
  "version": "1.0.0-*",

  "dependencies": {
    "Microsoft.AspNet.Mvc": "6.0.0-beta6",
    "Microsoft.AspNet.Server.IIS": "1.0.0-beta6",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-beta6",
    "Microsoft.AspNet.StaticFiles": "1.0.0-beta6",
    "System.IdentityModel.Tokens": "5.0.0-beta6-207211625",
    "Serilog.Framework.Logging": "1.0.0-beta-43",
    "Microsoft.AspNet.Authentication.OAuthBearer": "1.0.0-beta6"
  },

  "commands": {
    "web": "Microsoft.AspNet.Hosting --config hosting.ini"
  },

  "frameworks": {
    "dnx451": { }
  },

  "exclude": [
    "wwwroot",
    "node_modules",
    "bower_components"
  ],
  "publishExclude": [
    "node_modules",
    "bower_components",
    "**.xproj",
    "**.user",
    "**.vspscc"
  ]
}
  • порядок промежуточного ПО в методе настройки запуска имеет значение. UseOAuthBearerAuthentication нужно прийти перед UseMvc. Метод Configure при запуске.CS теперь выглядит следующим образом:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseOAuthBearerAuthentication();      

    app.UseMvc();
}

я работаю с ASP.NET 5 и пытается реализовать чрезвычайно простое доказательство концепции для генерации и потребления токенов JWT. Я читал статьи здесь, здесь и здесь но этот наиболее близко соответствует моим потребностям.

С этой целью, я очень внимательно прочитал статью, перечитал его, усвоил все комментарии, а затем встал простой пример. Теперь я могу создать токен JWT, но когда я пытаюсь вызвать действие контроллера, которое было украшено атрибутом authorize [Authorize ("Bearer")], я получаю следующее сообщение:

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

поскольку я не видел примера с высокой точностью A-to-Z о том, как это сделать, рассмотрите следующие шаги для воспроизвести:

  • создайте новый проект веб-API в Visual Studio 2015 (я использую Enterprise), выбрав "создать Project...Web...ASP.NET веб-приложение", а затем параметр "веб-API" в разделе "ASP.NET 5 Шаблоны предварительного просмотра"
  • использование бета-версии 5 SDK, global.json выглядит так:
{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.0-beta5",
    "runtime": "clr",
    "architecture": "x86"
  }
}
  • ввод зависимостей, необходимых для токенов JWT, project.json выглядит так это:
{
    "webroot": "wwwroot",
    "version": "1.0.0-*",

    "dependencies": {
        "Microsoft.AspNet.Mvc": "6.0.0-beta6",
        "Microsoft.AspNet.Server.IIS": "1.0.0-beta6",
        "Microsoft.AspNet.Server.WebListener": "1.0.0-beta6",
        "System.IdentityModel.Tokens": "5.0.0-beta5-206011020",
        "Microsoft.AspNet.Authentication.OAuthBearer": "1.0.0-beta5"
    },

    "commands": {
        "web": "Microsoft.AspNet.Hosting --config hosting.ini"
    },

    "frameworks": {
        "dnx451": { }
    },

    "exclude": [
        "wwwroot",
        "node_modules",
        "bower_components"
    ],
    "publishExclude": [
        "node_modules",
        "bower_components",
        "**.xproj",
        "**.user",
        "**.vspscc"
    ]
}
  • Автозагрузка.cs (это пример не предназначен для производства)
public class Startup
{
    const string        _TokenIssuer        = "contoso.com"             ;
    const string        _TokenAudience      = "contoso.com/resources"   ;
    RsaSecurityKey      _key                = null                      ;
    SigningCredentials  _signingCredentials = null                      ;

    public Startup(IHostingEnvironment env)
    {
        GenerateRsaKeys();
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddInstance(_signingCredentials);

        services.ConfigureOAuthBearerAuthentication
        (
            options =>
            {
                options.AutomaticAuthentication = true;
                options.TokenValidationParameters.IssuerSigningKey  = _key          ;
                options.TokenValidationParameters.ValidAudience     = _TokenAudience;
                options.TokenValidationParameters.ValidIssuer       = _TokenIssuer  ;
            }
        );

        services.ConfigureAuthorization
        (
            options =>
            {
                options.
                AddPolicy
                (
                    "Bearer",
                    new AuthorizationPolicyBuilder().
                        AddAuthenticationSchemes(OAuthBearerAuthenticationDefaults.AuthenticationScheme).
                        RequireAuthenticatedUser().
                        Build()
                );
            }
        );

        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerfactory)
    {
        app.UseMvc();

        app.UseOAuthBearerAuthentication();
    }

    void GenerateRsaKeys()
    {
        using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
        {
            _key = new RsaSecurityKey(rsa.ExportParameters(true));

            _signingCredentials = 
                new SigningCredentials
                (
                    _key                                    , 
                    SecurityAlgorithms.RsaSha256Signature   , 
                    SecurityAlgorithms.Sha256Digest         ,
                    "secret"
                );

            rsa.PersistKeyInCsp = false;
        }
    }
}
  • некоторые модели:

учетные данные.cs

public class Credentials
{
    public string user { set;get;}
    public string password { set;get;}
}

JwtToken.cs

public class JwtToken
{
    public string access_token  { set; get; }
    public string token_type    { set; get; }
}
  • контроллер токенов для извлечения токена (это пример не предназначен для производства), TokenController.cs:
[ Route("[controller]") ]
public class TokenController : Controller
{
    private readonly OAuthBearerAuthenticationOptions   _bearerOptions      ;
    private readonly SigningCredentials                 _signingCredentials ;

    public TokenController
    (
        IOptions<OAuthBearerAuthenticationOptions>  bearerOptions       ,
        SigningCredentials                          signingCredentials
    )
    {
        _bearerOptions      = bearerOptions.Options ;
        _signingCredentials = signingCredentials    ;
    }

    // POST: /token
    [HttpPost()]
    public JwtToken Token([FromBody] Credentials credentials)
    {
        // Pretend to validate credentials...

        JwtSecurityTokenHandler handler = 
            _bearerOptions                      .
            SecurityTokenValidators             .
            OfType<JwtSecurityTokenHandler>()   .
            First();

        JwtSecurityToken securityToken = 
            handler     .
            CreateToken
            (
                issuer              : _bearerOptions.TokenValidationParameters.ValidIssuer  ,
                audience            : _bearerOptions.TokenValidationParameters.ValidAudience,
                signingCredentials  : _signingCredentials                                   ,
                subject             : new ClaimsIdentity
                (
                    new Claim [] 
                    {
                        new Claim(ClaimTypes.Name,"somebody"),
                        new Claim(ClaimTypes.Role,"admin"   ),
                        new Claim(ClaimTypes.Role,"teacher" ),
                    }
                ) ,
                expires             : DateTime.Today.AddDays(1)
            );

        string token = handler.WriteToken(securityToken);

        return new JwtToken()
        {
            access_token    = token     ,
            token_type      = "bearer"
        };
    }
}
  • A контроллер значений для демонстрации приема маркера ValuesController.cs:
[Route("api/[controller]")]
public class ValuesController : Controller
{
    // GET: api/values
    [Authorize("Bearer")]
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/values/5
    [HttpGet("{id}")]
    public string Get(int id)
    {
        return "value";
    }
}
  • создать копию почтальон (или ваш любимый клиент REST), запустите пример приложения в Visual Studio и сделайте запрос POST, как к http: / / localhost: 22553 / token/ с телом JSON:
{
    "user" : "user",
    "password" : "secret"
}

приложение отвечает токеном:

{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6bnVsbH0.eyJ1bmlxdWVfbmFtZSI6InNvbWVib2R5Iiwicm9sZSI6WyJhZG1pbiIsInRlYWNoZXIiXSwiaXNzIjoiY29udG9zby5jb20iLCJhdWQiOiJjb250b3NvLmNvbS9yZXNvdXJjZXMiLCJleHAiOjE0Mzk1MzU2MDB9.anRgL10XFG_bKDDxY3D2xQSfhPRLGMjUTreQNsP1jDA6eRKwXHf3jtpCwm_saoWyUDFFA2TMI9e_LbP6F5l7vtozCluziE_GQkPkspUSWuWIpQJLPRTTPPZHGKmPmK4MLEl1zPPrggJWbvF9RBw3mMQ0KoMfjSL0vUQ8kZ7VXAel8dnYJccd-CFdnB6aDe79x2E9Se2iLxdhr--R_qgvfz1Fa6tR1dstqLQ-UjYqPWY4SOgBjM3abtjfLLVEzeQMVyezX7Cx9ObMXAGbGvQL6GB_T5RlfAoXWME4jM8Bzhd-07wwd732bBws4OXivj1sSz-qawNTnXmnuccLRtI1uA",
  "token_type": "bearer"
}
  • скопируйте маркер из предыдущего POST, затем в postman сделайте запрос GET как к http://localhost: 22553 / api / values, заботясь о том, чтобы добавить заголовок авторизации со значением "носитель YOURTOKEN" (например, носитель eyJ0eXAiOiJKV1QiLCJ...)

  • обратите внимание, что приложение отвечает с ошибкой:

1 ответов


вы должны зарегистрировать промежуточное по аутентификации на носителе OAuth2 перед MVC, или ваши пользователи будут неавторизованы при достижении MVC:

public class Startup {
    public void Configure(IApplicationBuilder app) {
        app.UseJwtBearerAuthentication(new JwtBearerOptions {
            // Your JWT bearer options.
        });

        app.UseMvc();
    }
}