HttpContext.User not populated in .NET Core app

173 Views Asked by At

I wonder why the User.GetUserId(); returns 0 wherever it's used. What's the problem?

Actually, the IsAuthenticated = false for the User object.

I tried to test my application using Postman and Angular client applications. In both ways, the token is returned to the client successfully. In Postman I add the received token to the authorization field of the header like this:

Bearer <the token>

After sending the request to another action that contains User.GetUserId(); I get the same result. and User.GetUserId(); is still 0.

Configure method in Startup.cs

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();
  
    app.UseCors(x => x
            .AllowAnyHeader()
            .AllowAnyMethod()
            .AllowAnyOrigin()
            .AllowCredentials()
            .WithOrigins("https://localhost:4200"));

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapFallbackToController("Index", "Fallback");
    });

}

Login method in AccountController:

[HttpPost("login")]
public async Task<ActionResult<UserDto>> Login(LoginDto loginDto)
{
    var user = await _userManager.Users
                                 .Include(p => p.Photos)
                                 .SingleOrDefaultAsync(x => x.UserName == loginDto.Username.ToLower());

    if (user == null) 
        return Unauthorized("Invalid username");

    var result = await _signInManager
                           .CheckPasswordSignInAsync(user, loginDto.Password, false);
 
    if (!result.Succeeded) 
        return Unauthorized();

    var token = await _tokenService.CreateToken(user);

    var userDto = new UserDto
        {
            Username = user.UserName,
            Token = token,
            KnownAs = user.KnownAs,
            Gender = user.Gender
        };

    var uId = User.GetUserId(); // it returns 0

    return userDto;
}

TokenService.cs:

public class TokenService : ITokenService
{
    private readonly SymmetricSecurityKey _key;
    private readonly UserManager<AppUser> _userManager;

    public TokenService(IConfiguration config, UserManager<AppUser> userManager)
    {
        _userManager = userManager;
        _key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["TokenKey"]));
    }

    public async Task<string> CreateToken(AppUser user)
    {
        var claims = new List<Claim>
                         {
                             new Claim(JwtRegisteredClaimNames.NameId, user.Id.ToString()),
                             new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName.ToString())
                         };

        var roles = await _userManager.GetRolesAsync(user);

        claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));

        var creds = new SigningCredentials(_key, SecurityAlgorithms.HmacSha512Signature);

        var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims),
                Expires = DateTime.Now.AddDays(7),
                SigningCredentials = creds
            };

       **//UPDATE**
       var claimsPrincipal = new ClaimsPrincipal(identity);
       _httpContextAccessor.HttpContext.User = new ClaimsPrincipal(identity);


        var tokenHandler = new JwtSecurityTokenHandler();

        var token = tokenHandler.CreateToken(tokenDescriptor);

        return tokenHandler.WriteToken(token);
    }
}

UPDATE

after updating CreateTokenAsync() as you can see in the code I got the proper result from User in the login controller after calling CreateTokenAsync(). but after that when I called another endpoint the HttpContext.User became empty! Having said that I injected IHttpContextAccessor into the class that CreateTokenAsync() is located.

0

There are 0 best solutions below