im using JWT to Authentication, and I’m storing it in Cookies. I want to use HttpContext.SignInAsync to login, I saw a lot of example with basic Cookie Auth, but not with JWT.
Here is my Startup.cs
services.AddTransient<IUserRepository, UserRepository>();
services.AddTransient<ITokenService, TokenService>();
IdentityModelEventSource.ShowPII = true;
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
};
options.SaveToken = true;
options.Events = new JwtBearerEvents();
options.Events.OnMessageReceived = context =>
{
if (context.Request.Cookies.ContainsKey("X-Access-Token"))
{
context.Token = context.Request.Cookies["X-Access-Token"];
}
return Task.CompletedTask;
};
})
.AddCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.IsEssential = true;
});
Here is my Login (Its currently working, but it would be bettern with SignInAsync
public IActionResult Login(LoginModel loginModel, string returnUrl)
{
if (string.IsNullOrEmpty(loginModel.UserName) || string.IsNullOrEmpty(loginModel.Password))
{
ViewBag.Message = "Nem lehet üres";
return View("Index",loginModel);
}
IActionResult response = Unauthorized();
var validUser = GetUser(loginModel);
if (validUser != null)
{
generatedToken = _tokenService.BuildToken(_config["Jwt:Key"].ToString(), _config["Jwt:Issuer"].ToString(),
validUser);
if (generatedToken != null)
{
Response.Cookies.Append("X-Access-Token", generatedToken, new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.Strict, Secure=true });
Response.Cookies.Append("X-Username", loginModel.UserName, new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.Strict, Secure=true });
//Response.Cookies.Append("X-Refresh-Token", user.RefreshToken, new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.Strict });
// HttpContext.Session.SetString("Token", generatedToken);
if (returnUrl != null)
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("MainWindow");
}
}
else
{
ViewBag.Message = "Nem jo token";
return View("Index", loginModel);
}
}
else
{
ViewBag.Message = "Nem jó user";
return View("Index", loginModel);
}
}
And here is my Token service:
public class TokenService : ITokenService
{
private const double EXPIRY_DURATION_MINUTES = 30;
public string BuildToken(string key, string issuer, User user)
{
var claims = new[] {
new Claim(ClaimTypes.Name, user.Name),
new Claim(ClaimTypes.Role, user.Role),
new Claim(ClaimTypes.NameIdentifier,
Guid.NewGuid().ToString())
};
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new JwtSecurityToken(issuer, issuer, claims,
expires: DateTime.Now.AddMinutes(EXPIRY_DURATION_MINUTES), signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
}
public bool IsTokenValid(string key, string issuer, string token)
{
var mySecret = Encoding.UTF8.GetBytes(key);
var mySecurityKey = new SymmetricSecurityKey(mySecret);
var tokenHandler = new JwtSecurityTokenHandler();
try
{
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = issuer,
ValidAudience = issuer,
IssuerSigningKey = mySecurityKey,
}, out SecurityToken validatedToken);
}
catch
{
return false;
}
return true;
}
}
Edit 1 – Added the question
How can I implement HttpContext.SignInAsync in this situation?
3
Answers
My startup like below:
Add more code:
Some code in this answer
In Login post method
I add below into the claims
And my token generated as below, when you login , you will get token.
Result:
Do you mean you want read claims from jwt and ceate a new ticket for cookie authentication as below:
just change authentication like below
authentication middleware do signin context automaticly