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.
User
to work. BecauseUser
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. – FreezedryClaimsPrincipal
. it helped a little but there is still a problem. I updated the question – Perspiration