User.IsInRole always returns false with Token Authentication

user2657943

I have ASP.NET Core 2 configured to use JWT Tokens to authenticate. The configuration looks like this:

services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;

    })
    .AddJwtBearer(options =>
    {
        options.RequireHttpsMetadata = false;
        options.SaveToken = true;

        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidIssuer = Configuration["Tokens:Issuer"],
            ValidAudience = Configuration["Tokens:Issuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
        };
    });

Then I created a method where a user signs in which looks like this:

[AllowAnonymous]
[HttpPost]
[Route("token")]
public async Task<IActionResult> Token([FromBody] LoginViewModel model)
{
    if (!ModelState.IsValid) return BadRequest("Could not create token");

    var user = await _userManager.FindByNameAsync(model.UserName);

    if (user == null) return BadRequest("Could not create token");
    var result = await _signInManager.CheckPasswordSignInAsync(user, model.Password, false);
    if (!result.Succeeded) return BadRequest("Could not create token");
    var claims = new[]
    {
        new Claim(JwtRegisteredClaimNames.Sub, user.Email),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
    };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Tokens:Key"]));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var roles = await _userManager.GetRolesAsync(user);

    var token = new JwtSecurityToken(_configuration["Tokens:Issuer"],
        _configuration["Tokens:Issuer"],
        claims,
        expires: DateTime.Now.AddMinutes(30),
        signingCredentials: creds);

    return Ok(new {
        access_token = new JwtSecurityTokenHandler().WriteToken(token),
        roles });
}

}

I save the token and use it in my request. I have a very simple api endpoint:

[HttpGet("users")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public IActionResult GetUsers()
{
    var isInRole = HttpContext.User.IsInRole(Roles.Administrator);
    return Ok(_service.GetAllUsers());
}

Here I get in the method, but isInRole is always false. Even though my var roles = await _userManager.GetRolesAsync(user); returns a list of roles including Administrator. Why does this not work then?

Denver Naidoo

You need to add the Role claim into your claims array like so

var claims = new[]
{
    new Claim(JwtRegisteredClaimNames.Sub, user.Email),
    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
    //role claim
    new Claim(ClaimTypes.Role, "Administrator")
};

This is what Asp.Net will look at in the [Authorize(Roles="Administrator")] attribute and HttpContext.User.IsInRole("Administrator");

Similarly ClaimTypes.Name is used to produce User.Identity.Name in your controller

I suggest you read the excellent article by Rui Figueiredo Secure a Web Api in ASP.NET Core on the subject

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related