I'm trying to use JWT in a core webapi application. Here is my Startup.ConfigureServices()
:
services.AddDbContextPool("Bla Bla");
services.AddIdentity<IdentityUser, IdentityRole>("Bla Bla");
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(o => {
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(c => {
c.RequireHttpsMetadata = false;
c.SaveToken = true;
c.TokenValidationParameters =
new TokenValidationParameters {
ValidIssuer = Configuration["JwtIssuer"],
ValidAudience = Configuration["JwtIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(Configuration["JwtKey"])),
ClockSkew = TimeSpan.Zero
};
});
services.AddRouting("Bla Bla");
services.AddMvcCore("Bla Bla").AddControllersAsServices();
And this is Startup.Configure()
method:
app.UseAuthentication();
app.UseMvc(rb =>
{ rb.MapRoute("api_default", "{controller}/{action}/{id?}"); });
Anyway, I have created a protect action to test (which I'm expecting to return an HTTP 401 Unauthorized
error):
public class AccountController : ControllerBase {
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public async Task<object> Info() {
return "Authorized!";
}
}
But its getting authorized and responsing "Authorized!" all the time. It seems the Authorize
attribute doesn't effect at all. Am I missing something?
P.S. I have tried both [Authorize]
and [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
attribute.
P.S.2 I have tried extending the controller from both ControllerBase
and Controller
.
P.S.3 I have tried without clearing default claims (removed this line JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
).
None of them worked.
Framework and packages info:
netcoreapp2.1
Microsoft.AspNetCore
Version = 2.1.6
Microsoft.AspNetCore.Authentication.JwtBearer
Version = 2.1.2
Microsoft.AspNetCore.Identity.EntityFrameworkCore
Version = 2.1.6
Microsoft.AspNetCore.Mvc.Core
Version = 2.1.3
UPDATE:
According to @sellotape's comment, I have returned the User
object from the action:
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public async Task<object> Info() {
return User;
}
And here is the output JSON:
{
"identities": [
{
"isAuthenticated": false,
"claims": [],
"roleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
"nameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
}
],
"identity": {
"isAuthenticated": false,
"claims": [],
"roleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
"nameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
},
"claims": []
}
The main issue is that when you use .AddMvcCore()
, you're only wiring up a small part of what you get when you use .AddMvc()
instead. For many solutions, it's simpler to just use the latter, as you then automatically get the following added and ready to use [source]:
If you prefer to only add what you absolutely need, you can elect to use .AddMvcCore()
instead, but then you need to explicitly add the MVC services you require; e.g. in this case (Authorization), you would need to
services.AddMvcCore()
.AddAuthorization();
Note how .AddAuthorization()
here is being applied to the result of services.AddMvcCore()
, which is an IMvcBuilder
, not to services
, which is an IServiceCollection
.