Reputation: 137
I have an ASP.NET Core site using AspNetCore.Identity.EntityFrameworkCore 1.1.1 and cookies to authorize/authenticate my users. No matter what I choose as my setting in the code below, the cookie expires after about 20 minutes and I can't figure why. The website will then no longer work unless you close the browser and clear the history/cookies. Any ideas?
services.AddIdentity<ApplicationUser, IdentityRole>(config =>
{
// Require a confirmed email in order to log in
config.SignIn.RequireConfirmedEmail = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
app.UseIdentity();
// Add cookie middleware to the configure an identity request and persist it to a cookie.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookie",
LoginPath = new PathString("/Account/Login/"),
AccessDeniedPath = new PathString("/Account/Forbidden/"),
AutomaticAuthenticate = true,
AutomaticChallenge = true,
ExpireTimeSpan = TimeSpan.FromMinutes(20),
SlidingExpiration = true,
});
I also have some razor code that controls whether to show the admin menu on the _layout page. This crashes when the cookie expires as the users suddenly has no claims. Is there a better way to handle this?
// If user is admin then show drop down with admin navigation
@if (User.HasClaim(System.Security.Claims.ClaimTypes.Role, "admin"))
{
<ul class="nav navbar-nav">
@*etc*@
</ul>
}
Upvotes: 4
Views: 21338
Reputation: 11
I personally use this way in order to use SignInManager in future:
builder.Services.AddDbContext<Server04DbContext>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("Local"));
}).AddIdentity<AppUser, IdentityRole>(options =>
{
options.SignIn.RequireConfirmedEmail = false;
options.User.RequireUniqueEmail = false;
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyz0123456789";
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
options.Password.RequireNonAlphanumeric = false;
options.Password.RequiredLength = 4;
}).AddDefaultTokenProviders().AddEntityFrameworkStores<Server04DbContext>();
builder.Services.ConfigureApplicationCookie(options =>
{
options.LoginPath = new PathString("/Auth/Login");
options.LogoutPath = new PathString("/Auth/Logout");
options.AccessDeniedPath = new PathString("/Home/AccessDenied");
options.Cookie = new()
{
Name = "IdentityCookie",
HttpOnly = true,
SameSite = SameSiteMode.Lax,
SecurePolicy = CookieSecurePolicy.Always
};
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromDays(30);
});
Upvotes: 0
Reputation: 137
I think the problem was that I was persisting data to a cookie with different settings.
Not sure if it's the proper way to do it, but I was able to solve the problem by using both services.AddIdentity and app.UseCookieAuthentication as below.
In ConfigureServices, set the cookie for log in:
// set the cookie for sign in
services.AddIdentity<ApplicationUser, IdentityRole>(config =>
{
// Require a confirmed email in order to log in
config.SignIn.RequireConfirmedEmail = true;
// Cookie settings
config.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromHours(10);
config.Cookies.ApplicationCookie.LoginPath = "/Account/LogIn";
config.Cookies.ApplicationCookie.LogoutPath = "/Account/LogOut";
}).AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
In Configure set the cookie scheme used to persist claims:
// Add cookie middleware to the configure an identity request and persist it to a cookie.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookie",
LoginPath = new PathString("/Account/Login/"),
AccessDeniedPath = new PathString("/Account/Forbidden/"),
AutomaticAuthenticate = true,
AutomaticChallenge = true,
//ExpireTimeSpan = TimeSpan.FromSeconds(10),
ExpireTimeSpan = TimeSpan.FromHours(10),
SlidingExpiration = true,
});
In the log in method, persist the claims:
await HttpContext.Authentication.SignInAsync("Cookie", userPrincipal);
Upvotes: 0
Reputation: 2114
You do not need a separate CookieAuthentication middleware when you are using ASPNET identity. UseIdentity()
will do that for you and generate a cookie. You can set the "cookie options"
in the AddIdentity block of the application like so:
services.AddIdentity<ApplicationUser, IdentityRole>(config =>
{
// Require a confirmed email in order to log in
config.SignIn.RequireConfirmedEmail = true;
// Your Cookie settings
config.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromDays(1);
config.Cookies.ApplicationCookie.LoginPath = "/Account/LogIn";
config.Cookies.ApplicationCookie.LogoutPath = "/Account/LogOut";
}).AddEntityFrameworkStores<ApplicationDbContext().AddDefaultTokenProviders();
Also, take a look at https://stackoverflow.com/a/34981457/1137785, it gives a background of this sort of a scenario with a very good explanation.
Upvotes: 4