4

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>
}
Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
Dan Young
  • 137
  • 1
  • 2
  • 12

2 Answers2

4

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.

Muqeet Khan
  • 2,094
  • 1
  • 18
  • 28
  • Thanks @Muqeet. Your response helped me to solve my problem! – Dan Young Jun 12 '17 at 17:14
  • @muqeetKhan In [this](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity?tabs=visual-studio%2Caspnetcore1x#tabpanel_yS0QDAFpXJ-1_aspnetcore1x) new ASP.NET article they are using the following to setup the options. What is the difference in your approach and the article's approach, do you know? `// Configure Identity services.Configure(options => {.....}` – nam Oct 19 '17 at 21:49
  • 1
    @nam just different extension methods. In my example, I am using the extension method that takes the `options` object which is then configured in DI within the method. In the link you gave, they are just doing it separately. Its open source yay! look here on [github](https://github.com/aspnet/Identity/blob/patch/1.1.4/src/Microsoft.AspNetCore.Identity/IdentityServiceCollectionExtensions.cs) – Muqeet Khan Oct 19 '17 at 22:14
  • 6
    Either I am blind, or in 3.1 `config.Cookies` is gone. How should I configure the `LoginPath` now? – LOST Mar 25 '20 at 19:07
  • 3
    It's been moved to services.ConfigureApplicationCookie(configure => { ... }); – D-Mac Jun 07 '21 at 03:54
0

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);
MarredCheese
  • 17,541
  • 8
  • 92
  • 91
Dan Young
  • 137
  • 1
  • 2
  • 12