HttpContext.User not populated in .NET Core app
Asked Answered
P

0

1

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.

Perspiration answered 12/12, 2023 at 16:31 Comment(3)
I’d suggest you to use the built-in authentication services to handle your authentication, and use ASP.NET Core Identity if you want a login functionality with your own user accounts. If you roll your own login mechanism, you will need to hook into the authentication stack if you want e.g. User to work. Because User will just look at the claims identity that is provided by the authentication middleware but the way you set it up, no claims identity is set up.Freezedry
Try specific the scheme :[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] Identity would modify your default authentication shcemeDud
@Freezedry thanks for your response. I used ClaimsPrincipal. it helped a little but there is still a problem. I updated the questionPerspiration

© 2022 - 2024 — McMap. All rights reserved.