Ошибка ASP.NET Core 2.0 JWT завершается с ошибкой `Authorization для пользователя: (null)` error

Я использую приложение ASP.NET Core 2.0 (Web API) в качестве JWT-эмитента для создания токена, который может использоваться мобильным приложением. К сожалению, этот токен не может быть проверен одним контроллером, а может быть подтвержден другим (с использованием того же параметра проверки в том же приложении asp.net core 2.0).

Итак, у меня есть токен, который действителен и может быть декодирован, имеет все необходимые претензии и временные метки. Но одна конечная точка принимает его, а другая дает мне ошибку 401 и debug:

Microsoft.AspNetCore.Authorization.DefaultAuthorizationService: Информация: Ошибка авторизации для пользователя: (null).

[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed for user: (null).
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: (null).
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
      Executing ChallengeResult with authentication schemes ().
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12]
      AuthenticationScheme: Bearer was challenged.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: Bearer was challenged.
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action MyController.Get (WebApi) in 72.105ms
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action MyController.Get (WebApi) in 72.105ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 271.077ms 401 
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 271.077ms 401 

Моя настройка проверки ниже:

var secretKey = Configuration["Authentication:OAuth:IssuerSigningKey"];
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));
var tokenValidationParameters = new TokenValidationParameters
{
   ValidateIssuerSigningKey = true,
   IssuerSigningKey = signingKey,
   ValidateIssuer = true,
   ValidIssuer = Configuration["Authentication:OAuth:Issuer"],
   ValidateAudience = true,
   ValidAudience = Configuration["Authentication:OAuth:Audience"],
   ValidateLifetime = true,
   ClockSkew = TimeSpan.Zero,
};

services.AddAuthentication(options =>
{
   options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
   options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
   options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.RequireHttpsMetadata = false;
    options.TokenValidationParameters = tokenValidationParameters;
});

Эти две конечные точки идентичны, просто живут в разных контроллерах, оба отмечены атрибутом Authorize.

Как это возможно?

Ответ 1

Последовательность операторов добавления в функции configure имеет важное значение. Убедитесь, что

app.UseAuthentication();

предшествует

app.UseMvc();

Возможно, это была проблема?

Ответ 2

В методе startup.cs ConfigureServices, если вы добавили

services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options => ...

Объяснение: Когда вы используете [Авторизовать] на контроллере, он по умолчанию привязывается к первой системе авторизации.

options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;

При этом вы устанавливаете свою настройку по умолчанию для проверки подлинности на стороне JWT.

дополнительно вы можете добавить

options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

эта строка - как предотвратить получение 404 ошибок при использовании Identity с JWT. Если вы используете идентификатор, DefaultChallengeScheme попытается перенаправить вас на страницу входа в систему, которая, если она не существует, приведет к тому, что 404 не будет найден, а не 401 неавторизован. установив DefaultChallengeScheme на JwtBearerDefaults.AuthenticationScheme по неавторизованным, больше не будет пытаться перенаправить вас на страницу входа в систему

Если вы используете аутентификацию cookie с проверкой подлинности JWT в теге [Авторизовать], вы можете указать, какой именно идентификатор authenticationScheme вы хотите. например

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

Ответ 4

попробуйте это в startup.cs

services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(opts => ...

Ответ 5

Это похоже на поведение, которое вы получаете, когда ваш JWT не проверен правильно. У меня была эта проблема в результате ввода "Перенос: (JWT)" вместо "Bearer (JWT)" в заголовке

Ответ 6

Когда аутентификации добавляются как:

  services.AddAuthentication(options => {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        ....

Это означает, что каждый атрибут [Authorize], который помещается поверх метода или класса контроллера, будет пытаться выполнить аутентификацию по схеме аутентификации по умолчанию (в данном случае JwtBearer), И НЕ БУДЕТ КАСКАДИРОВАННО, чтобы попытаться аутентифицироваться с другими схемами. это может быть объявлено (как схема Cookie). Чтобы аутентифицировать AuthorizeAttribute по схеме cookie, его нужно указать следующим образом:

[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]

Это будет работать и наоборот, т.е. Если схема cookie используется по умолчанию, тогда схема JwtBearer должна быть объявлена для авторизации для тех методов или контроллеров, которым потребуется аутентификация токена JwtBearer.

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

Ответ 7

Проверьте кодировку ключа подписи в вашем провайдере токенов, это может быть, например, UTF8, а не ASCII.

Ответ 8

Вы можете попробовать это вместо этого:

.AddJwtBearer(options =>
{
    options.RequireHttpsMetadata = false;
    options.TokenValidationParameters = tokenValidationParameters;
});'