I want to use claim base Authorization in ASP.NET CORE Web API, I think my code is true but, it does not work for me and gives me the error 403 forbidden however I use the Right Token which has the right claim value in my AspNetUserClaims table
here is my Program.cs code
//Get Connection String
builder.Services.AddDbContext<AppDbContext>(opts =>
opts.UseNpgsql(builder.Configuration["connection:connectionString"]));
builder.Services.Configure<ApplicationSettings>(builder.Configuration.GetSection("ApplicationSettings"));
builder.Services.AddMvc();
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<AppDbContext>();
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("VIEW",
policy => policy.RequireClaim("VIEW"));
});
builder.Services.Configure<IdentityOptions>(options =>
options.User.RequireUniqueEmail = true);
//JWT Token Setup
var key = Encoding.UTF8.GetBytes(builder.Configuration["ApplicationSettings:JWT_Secret"]);
builder.Services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x => {
x.RequireHttpsMetadata = false;
x.SaveToken = false;
x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
};
});
here is my UsersLoginController when the user login, this controller generates the Token after successful login
[HttpPost]
[Route("Login")]
public async Task<IActionResult> Login(LoginModel model)
{
var user = await _userManager.FindByNameAsync(model.UserName);
if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
{
//Get role assigned to the user
var role = await _userManager.GetRolesAsync(user);
IdentityOptions _options = new IdentityOptions();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim("UserID",user.Id.ToString()),
new Claim(_options.ClaimsIdentity.RoleClaimType,role.FirstOrDefault())
}),
Expires = DateTime.UtcNow.AddDays(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.JWT_Secret)), SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(securityToken);
return Ok(new { token });
}
else
return BadRequest(new { message = "Username or password is incorrect." });
}
}
here is my UsersProfileDetailsController
[HttpGet]
[Authorize(Policy = "VIEW")]
public async Task<Object> GetUserProfile()
{
string userId = User.Claims.First(c => c.Type == "UserID").Value;
var user = await _userManager.FindByIdAsync(userId);
var role = await _userManager.GetRolesAsync(user);
return new
{
user.Id,
user.FirstName,
user.LastName,
user.Email,
user.UserName,
user.PhotoPath,
role,
};
}
Now when I login with Admin User which has the right Claimvalue VIEW in the Table AspNetUserClaims, it generates the Token for me but when I use this Token to access UserDetails from UsersProfileDetailsController it gives me the code 403 forbidden.
Can anyone help me with how to implement Claims base Authorization and what are my problems?
I use Postman for testing.
CodePudding user response:
because you configured authoriztion as below:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("VIEW",
policy => policy.RequireClaim("VIEW"));
});
If you Press F12 and go to definition,you'll find the explaination of
the method

you added [Authorize(Policy = "VIEW")] on your controller, if you want authorize successfully, when you generate the token,you have to add the claim VIEW
Subject = new ClaimsIdentity(new Claim[]
{
new Claim("UserID",user.Id.ToString()),
//add a new claim named View here
new Claim("View",.......),
new Claim(_options.ClaimsIdentity.RoleClaimType,role.FirstOrDefault())
}),
