I implemented a JWT token authentication where the register and login are working fine.
This is what I normally do with inbuilt authentication
var currentUser = await _userManager.GetUserAsync(HttpContext.User);
var category = _context.Categories.Where(m=>m.ApplicationUserId == currentUser.Id);
return View(await category.ToListAsync());
I will get the current logged in user from the httpContext, then match the current user id(that is the application user Id of the current user) with the application userid and return the matching list.
if the condition did not match then do something else.
I cant seem to get this with JWT authentication. I am using blazor client
I have tried different approach but still not getting it. I thought I could get the current user like this but I the application user Id. I was getting the username of the current user.
internal async Task<List<Staff>> GetAllStaffServices()
{
var currentUser = httpContextAccessor.HttpContext.User.Identity.Name.ToString();
var another = userManager.FindByNameAsync(currentUser);
//var userId = this.User.FindFirst(ClaimTypes.NameIdentifier).Value;
var staff = applicationDbContext.Staffs.Where(m => m.ApplicationUserId == another.Id);
return await staffs.ToListAsync();
}
This is my login method
public async Task<IActionResult> Login([FromBody] LoginModel login)
{
var result = await _signInManager.PasswordSignInAsync(login.UserName, login.Password, false, false);
if (!result.Succeeded) return BadRequest(new LoginResult { Successful = false, Error = "Username and password are invalid." });
var user = await _signInManager.UserManager.FindByNameAsync(login.UserName);
var roles = await _signInManager.UserManager.GetRolesAsync(user);
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, login.UserName));
claims.Add(new Claim(JwtRegisteredClaimNames.Jti, user.Id));
claims.Add(new Claim(JwtRegisteredClaimNames.Email, user.Email));
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtSecurityKey"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var expiry = DateTime.Now.AddDays(Convert.ToInt32(_configuration["JwtExpiryInDays"]));
var token = new JwtSecurityToken(
_configuration["JwtIssuer"],
_configuration["JwtAudience"],
claims,
expires: expiry,
signingCredentials: creds
);
return Ok(new LoginResult { Successful = true, Token = new JwtSecurityTokenHandler().WriteToken(token) });
}
}
config services
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<RegisterInfoModel>().AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["JwtIssuer"],
ValidAudience = Configuration["JwtAudience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"]))
};
});
services.AddScoped<StaffServices>();
services.AddMvc().AddNewtonsoftJson();
services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "application/octet-stream" });
});
}
Now you can, in your Web Api end point annotated by Authorize attribute, code something like this:
var userName = HttpContext.User.Identity.Name.ToString();
var user= userManager.FindByNameAsync(userName);
var staff = applicationDbContext.Staffs.Where(m => m.ApplicationUser.Id ==
user.Id);
return await staffs.ToListAsync();
Note: No need to use HttpContextAccessor... HttpContext is available in the controller
The code here is very similar to yours. It extricates the user name from the HttpContext, call the FindByNameAsync to retrieve the user, and then use it.
Please, run it and report if its OK. If not, report the issue.
Update: If you wish to add the user Id to the Jwt token, in addition to the user name, you should do the following in your Login method:
claims.Add(new Claim(ClaimTypes.Name, login.UserName));
claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id));
And to get the user id from the GetAllStaffServices method, you can call UserManager.GetUserId, passing it a claims principal object extracted from HttpContext:
var userId = UserManager.GetUserId (HttpContext.User);
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments