Reputation: 1773
I am having an issue, when I am trying to use [Authorize(Roles = "Administrator")]
in my controllers, it always returns 403
. I am using Identity and JWT tokens. Here's my Startup.cs
. I am calling both app.UseAuthentication()
and app.UseAuthorization()
in ConfigureServices()
, but still the same, everytime it returns 403
public void ConfigureServices(IServiceCollection services)
{
...
services.AddIdentity<User, Role>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequiredUniqueChars = 0;
options.Password.RequiredLength = 6;
options.ClaimsIdentity.UserIdClaimType = "user_id";
options.ClaimsIdentity.UserNameClaimType = "email";
options.ClaimsIdentity.RoleClaimType = "user_role";
})
.AddRoles<Role>()
.AddEntityFrameworkStores<MyDbContext>()
.AddDefaultTokenProviders();
var key = Encoding.UTF8.GetBytes(Configuration["ApplicationSettings:JwtKey"].ToString());
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.SaveToken = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateAudience = false,
ValidateIssuer = false,
IssuerSigningKey = new SymmetricSecurityKey(key),
ClockSkew = TimeSpan.Zero
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
context.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
};
});
services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Here's how I am creating token
private async Task<string> GenerateToken(DataModelUser user)
{
var key = Encoding.UTF8.GetBytes(_appSettings.JwtKey);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim("user_role", user.Role.ToString()),
new Claim("user_id", user.Id.ToString()),
new Claim("email", user.Email)
}),
Expires = DateTime.UtcNow.AddDays(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(securityToken);
}
And I am adding like this on my controller
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ProfileController : ControllerBase
{
[HttpGet]
[Authorize(Roles = "Administrator")]
public async Task<IActionResult> Get()
{
return Ok();
}
}
Here's my JWT token payload!
{
"user_role": "Administrator",
"user_id": "5a6333f1-9696-4b1c-a8f8-04619ebd686d",
"name": "Admin Admin",
"completed_profile": "False",
"email": "[email protected]",
"nbf": 1597147248,
"exp": 1597233648,
"iat": 1597147248
}
Upvotes: 2
Views: 2627
Reputation: 21
I had a similar issue, and I resolved it by adding RoleClaimType and NameClaimType to the TokenValidationParameter:
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateAudience = false,
ValidateIssuer = false,
IssuerSigningKey = new SymmetricSecurityKey(key),
ClockSkew = TimeSpan.Zero,
RoleClaimType = IdentityModel.JwtClaimTypes.Role,
NameClaimType = IdentityModel.JwtClaimTypes.Name
};
Upvotes: 2