Search code examples
c#asp.net-coreauthenticationclaims

ArgumentNullException: Value cannot be null. (Parameter 'value')


I am having trouble with loging in from postman to my API. I get the roles back no problem but when they are used as parameters in the tokenservice they just stop working I get the following error :

Error

This is my endpoint :


 [HttpPost("login")]
        public async Task<IActionResult> Login(LoginUser loginData)
        {
            var userFromDb = await _userManager.FindByNameAsync(loginData.UserName);

            if (userFromDb == null) return NotFound();

            var result = await _signinManager.CheckPasswordSignInAsync(userFromDb, loginData.Password, false);

            if (result == null) return BadRequest("Invalid Password");

            var role = await _userManager.GetRolesAsync(userFromDb);

            return Ok(
                    new
                    {
                        result = result,
                        username = userFromDb.UserName,
                        email = userFromDb.Email,
                        token = _tokenService.GenerateToken(userFromDb, role)
                    }
             );



        }

And this is the Token Service :

public class TokenService : ITokenService
    {

        private readonly IConfiguration _config;

        public TokenService(IConfiguration config)
        {
            _config = config;
        }

        public string GenerateToken(IdentityUser user, IList<string> roles)
        {
            var claims = new List<Claim>
            {
                new Claim(JwtRegisteredClaimNames.GivenName, user.UserName),
                new Claim(JwtRegisteredClaimNames.Email, user.Email)
            };

            if (roles != null)
            {
                foreach (var role in roles)
                {
                    claims.Add(new Claim(ClaimTypes.Role, role));
                }
            }

            

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Token:Key"]));

            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);

            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims),
                Expires = DateTime.Now.AddDays(7),
                SigningCredentials = creds,
                Issuer = _config["Token:Issuer"],
            };

            var tokenHandler = new JwtSecurityTokenHandler();

            var token = tokenHandler.CreateToken(tokenDescriptor);

            return tokenHandler.WriteToken(token);

I have tried to rewrite my code and espacially this part :

 if (roles != null)
            {
                foreach (var role in roles)
                {
                    claims.Add(new Claim(ClaimTypes.Role, role));
                }
            }

because when I put an entry point in the token service it tells me that role is null


Solution

  • I checked your code on my application, the code works well, check the following screenshot:

    enter image description here

    The issue might relates the userFromDb, role value or the configuration value, I suggest you could set some break point to check the userFromDb and role value in the Login method and set break point in the TokenService to check whether the token generated success, refer to the following image:

    enter image description here

    Update: the LoginUser:

    public class LoginUser
    {
        public string UserName { get; set; }
        public string Password { get; set; }
        public string EmailAddress { get; set; }
    }
    

    For the IdentityUser, I'm using the Asp.net core Identity default IdentityUser model. because in your code, the GenerateToken method also use the IdentityUser Model.

    I think you it is because I am using my own user instead of IdentityUser

    You can check the GenerateToken method and check the userFromDb, might the issue relate it, in the GenerateToken method, you might need to change your code to use your custom user model, instead of the IdentityUser model.