ASP.NET Core 2.0 JWT Validation fails with `Authorization failed for user: (null)` error
Solution 1
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?
Solution 2
For Dotnetcore 3.1, I placed app.UseAuthentication()
before app.UseAuthorization()
Solution 3
In your startup.cs ConfigureServices method if you add
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => ...
Explanation: When you use [Authorize] on a controller it binds to the first authorization system by default.
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
With this you are setting your default to JWT Bearer authentication.
additionally you can add
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
this line is how to prevent getting 404 not found errors when using Identity with JWTs. If you are using identity the DefaultChallengeScheme will try to redirect you to a login page, which if non existent will result in getting a 404 not found rather than the wanted 401 unauthorized. by setting the DefaultChallengeScheme to JwtBearerDefaults.AuthenticationScheme on unauthorized it will no longer try to redirect you to a login page
If you are using Cookie Authentication with JWT authentication in the [Authorize] tag you can specify what authenticationScheme you want. for example
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
Solution 4
For anyone using .NET Core 3.1
, this is how it works:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("AllowOrigin");
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Solution 5
I added:
app.UseAuthentication();
In Startup.Configure()
and that resolved this error for me.
Reference: Auth 2.0 Migration announcement
Alexey Strakh
Updated on October 31, 2020Comments
-
Alexey Strakh over 3 years
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?