ASP.NET Core 2.0 JWT Validation fails with `Author

2020-02-04 06:17发布

I'm using ASP.NET Core 2.0 application (Web API) as a JWT issuer to generate a token consumable by a mobile app. Unfortunately, this token couldn't be validated by one controller while can be validated by another (using the same validation setting within the same asp.net core 2.0 app).

So I have a token which is valid and could be decoded, has all the required claims and timestamps. But one endpoint accepts it, while another gives me 401 error and debug output:

Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: (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 

My validation setup is below:

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;
});

These two endpoints are identical, just live in different controllers, both marked with the Authorize attribute.

How is that possible?

8条回答
我命由我不由天
2楼-- · 2020-02-04 07:00

This seems to be the behavior you receive when your JWT isn't validated correctly. I had this problem as a result of typing "Bearer: (JWT)" instead of "Bearer (JWT)" in the header

查看更多
beautiful°
3楼-- · 2020-02-04 07:06

When Authentications are added like:

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

It means that every attribute [Authorize] that is put on top of a method or a controller class, will try to authenticate against the default authentication schema (in this case the JwtBearer) AND IT WILL NOT CASCADE DOWN to try to authenticate with other schemas that might be declared (like Cookie schema). In order to make the AuthorizeAttribute authenticate against the cookie schema it has to be specified like

[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]

This will work also the other way around, i.e. if cookie schema is default then the JwtBearer schema must be declared for authorization for those methods or controllers that would need JwtBearer token authentication

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
查看更多
够拽才男人
4楼-- · 2020-02-04 07:09

The sequence of the add statements in the configure function is of importance. Make sure that

app.UseAuthentication();

comes before

app.UseMvc();

Might this have been the problem?

查看更多
狗以群分
5楼-- · 2020-02-04 07:12

Check signing key encoding in your token provider it can be for example UTF8 not ASCII.

查看更多
Viruses.
6楼-- · 2020-02-04 07:14

try this in startup.cs

services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(opts => ...
查看更多
太酷不给撩
7楼-- · 2020-02-04 07:17

You can try this instead:

.AddJwtBearer(options =>
{
    options.RequireHttpsMetadata = false;
    options.TokenValidationParameters = tokenValidationParameters;
});'
查看更多
登录 后发表回答