Hi All,
How to implement the remember me?
what I expect is if the user select the "remember me" then if they logged out and come back again they should not need to enter their user email and password.
I use NetCore 6 C# below, the IsPersistent is true but when the user logout, it goes to login page but it doesn't automatically filled with the last user logged in info.
please help.. thank you
**program.cs**
builder.Services.AddScoped<IUserManager, UserManager>();
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddDbContext<CookieReadersContext>(options =>
{
options.UseNpgsql(pgSQLConnectionString);
});
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
options.LoginPath = "/User/Login";
options.ReturnUrlParameter = "ReturnUrl";
options.AccessDeniedPath = "/User/Login";
options.LogoutPath = "/User/Logout";
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(300
);
options.Cookie.MaxAge = options.ExpireTimeSpan;
});
builder.Services.AddTransient<CustomCookieAuthenticationEvents>();
builder.Services.AddHttpContextAccessor();
builder.Services.AddMemoryCache();
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.Secure = CookieSecurePolicy.Always;
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
app.UseCookiePolicy();
**login.cs**
public class Login
{
[Required]
[EmailAddress]
[Display(Name = "User Email Address")]
public string userEmail { get; set; } = "";
[Required]
[DataType(DataType.Password)]
[Display(Name = "User Password")]
public string userPassword { get; set; } = "";
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
public interface IUserRepository
{
CookieUserItem Validate(Views.User.Login model);
}
public class UserRepository : IUserRepository
{
private CookieReadersContext _db;
public UserRepository(CookieReadersContext db)
{
_db = db;
}
public CookieUserItem Validate(Views.User.Login login)
{
// validate login here
}
}
public interface IUserManager
{
Task SignIn(HttpContext httpContext, CookieUserItem user, bool isPersistent);
Task SignOut(HttpContext httpContext);
}
public class UserManager : IUserManager
{
public async Task SignIn(HttpContext httpContext, CookieUserItem user, bool isPersistent)
{
string authenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme;
// Generate Claims from DbEntity
var claims = GetUserClaims(user);
// Add Additional Claims from the Context
// which might be useful
// claims.Add(httpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name));
ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, authenticationScheme);
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
var authProperties = new AuthenticationProperties
{
IsPersistent = isPersistent
// AllowRefresh = <bool>,
// Refreshing the authentication session should be allowed.
// ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
// The time at which the authentication ticket expires. A
// value set here overrides the ExpireTimeSpan option of
// CookieAuthenticationOptions set with AddCookie.
// IsPersistent = true,
// Whether the authentication session is persisted across
// multiple requests. Required when setting the
// ExpireTimeSpan option of CookieAuthenticationOptions
// set with AddCookie. Also required when setting
// ExpiresUtc.
// IssuedUtc = <DateTimeOffset>,
// The time at which the authentication ticket was issued.
// RedirectUri = "~/Account/Index"
// The full path or absolute URI to be used as an http
// redirect response value.
};
await Models.Users.Update_Last_Login(user.usersPid);
await httpContext.SignInAsync(authenticationScheme, claimsPrincipal, authProperties);
}
public async Task SignOut(HttpContext httpContext)
{
await httpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
private List<Claim> GetUserClaims(CookieUserItem user)
{
List<Claim> claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.PrimarySid, user.usersPid.ToString()));
claims.Add(new Claim(ClaimTypes.Name, user.userName));
claims.Add(new Claim(ClaimTypes.Email, user.userEmail));
return claims;
}
**UserController.cs
**
[HttpPost]
[Route("/User/Login/")]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(Views.User.Login login)
{
if (login.ReturnUrl == null)
login.ReturnUrl = "";
if (!ModelState.IsValid)
return View(login);
var user = _userRepository.Validate(login);
// do some tasks based on returning user
}
[HttpGet]
[Route("/User/Logout")]
public async Task<IActionResult> Logout()
{
await _userManager.SignOut(this.HttpContext);
return RedirectPermanent("~/Home/");
}