Reputation: 752
I have a custom login that returns a token in the token the user role should be included and his custom policies. I do not know how to add the custom policies in the tokens subject.
I have tried to hard code it but when I try it in postman I get this error: The AuthorizationPolicy named: 'ViewClients' was not found
.
How can I solve this thank you.
[HttpPost, Route("login")]
public async Task<IActionResult> Login([FromBody] LoginModel user)
{
string passowrdHashed = HashPassword(user.Password);
var userFromDb = await _userManager.FindByNameAsync(user.UserName);
if (userFromDb == null)
{
return Unauthorized();
}
else if (user != null && userFromDb.UserName == user.UserName
&& userFromDb.PasswordHash == passowrdHashed)
{
if (userFromDb.PasswordHash == HashPassword(_employeeService.DEFAULT_PASSWORD))
{
return Ok("Please change password!");
}
else
{
List<Entities.Type> roles = await _roleService.GetAllUserRoles();
var userRole = await _employeeRoleService.GetUserRoleByUserId((ulong)userFromDb.Id);
Entities.Type role = roles.Where(x => x.Id == userRole.RoleId).FirstOrDefault();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[] {
new Claim("Policy", "ViewClients"),//THIS LINE IS PROBLEMATIC!!!
new Claim(ClaimTypes.Role, role.NormalizedName),
// "comercial" )// userRole.NormalizedName)
}),
Issuer = "jcortenbach",
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MySupperSecretKey")), SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(securityToken);
return Ok(new { token });
}
}
else
{
return Unauthorized();
}
}
I want this API to work when user has the policy ViewClients
.
// GET api/clients
[HttpGet]
[Authorize(Policy = "ViewClients")]
public async Task<IEnumerable<ClientViewModel>> GetAsync(bool isDeleted)
{
//Returns List of clients
}
Upvotes: 0
Views: 1839
Reputation: 1182
I think you are confusing two different concepts. The Authorize attribute will not directly check the claims on your token. You must use policies for that.
The [Authorize(Policy = <policyname>)]
attribute will search for a registered policy that in turn can be configured to check the claims you specify for any given value.
In your case you need to configure your pipeline to use Authorization and register a policy, e.g. as follows:
services.AddAuthorization(options =>
{
options.AddPolicy(
"ViewClients",
policy => policy.RequireClaim(ClaimTypes.Role, "ViewClients")
);
});
The above creates a policy called ViewClients
that checks for a Role claim that contains the value "ViewClients". So the corresponding claim is:
new Claim(ClaimTypes.Role, "ViewClients")
You can reconfigure that to suit whatever your needs are.
One remark:
I am not sure if your service is intended to be used in production, but a line that immediately caught my eye was:
userFromDb.PasswordHash == HashPassword(_employeeService.DEFAULT_PASSWORD)
You should reconsider giving every new user the same default password. Generally speaking it's safer to configure an expiring, random default password and set a boolean flag to the database to indicate a user needs to change his password upon next login.
Upvotes: 1