6

I'm trying to get a persistent connection so the users only have to use their password once. I've used this doc: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?tabs=aspnetcore2x but the users still get disconnected after a while.

await HttpContext.SignInAsync(
                    CookieAuthenticationDefaults.AuthenticationScheme,
                    principal,
                    new AuthenticationProperties
                    {
                        IsPersistent = true
                    });

What can I do to get a really persistent connection ?

2 Answers 2

6

The persistence granted by IsPersistent is, according to the docs, only meant to imply that the authentication will persist through browsing sessions (that is, it is kept even when the browser is closed). You need a combination of Persistence and to set an expiration time for the cookie. The expiration of the cookie can be set via the CookieAuthenticationOptions (MSDN), using the ExpireTimeSpan option.

Without persistence, expiration of the authentication can be set using the ExpiresUtc option in AuthenticationOptions,

Sign up to request clarification or add additional context in comments.

5 Comments

Alright I'll try that. Just one thing, the doc says: The ExpiresUtc and IsPersistent properties are mutually exclusive. Doesn't that mean I can't use both at the same time ?
@GlobalFx So absolute expiry (via ExpiresUtc) will reject the set cookie even if the user hasn't closed the browser. IsPersistent means that the user's authentication lifetime is then dictated by the CookieAuthenticationOptions. Setting isPersistent to false means that users are only authenticated for their current browsing session, which will be cleared when the browser is closed.
Ok, so the solution would be to set IsPersistent to true and set ExpireTimeSpan to let's say a year in ConfigureServices without setting ExpiresUtc. The users would only have to login once a year right ?
I believe so! No matter what your app uses cookies. If you don't have persistence set, then the cookies are cleared on closing the browser. If you do have persistence, then the cookies need an expiration date, set by your TimeSpan.
Great ! Wanna update your answer so I can accept it ?
4

There are few things you should notice when implement persistent cookie authentication.

Configure sliding expiration for cookie in Startup.cs. It will be clearer if you explicitly set values that you needed and don't use default settings.

private void ConfigureAuthentication(IServiceCollection services)
{
    services
        .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(options =>
        {                 
            // true by default   
            options.SlidingExpiration = true;

            // 14 days by default
            options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
        });
}

When user check flag "Remember Me" configure cookie to persist across browser sessions and set absolute expiration (as long as you want). This settings will override SlidingExpiration and ExpireTimeSpan. In login action:

List<Claim> claims = new List<Claim>();
// Prepare user claims...
                
var userIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);

AuthenticationProperties authenticationProperties = new AuthenticationProperties() { IsPersistent = model.RememberMe };
if (model.RememberMe)
{
    // One month for example
    authenticationProperties.ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(1);
}

await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, authenticationProperties);

Confugure data protection. Remember machineKey in old classic asp.net webforms. Otherwise cookie will be reset after every IIS app pool restart. You should configure data protection before authentication in Startup.cs. To store keys in root folder of your app:

private void ConfigureDataProtection(IServiceCollection services, IWebHostEnvironment environment)
{
    var keysDirectoryName = "Keys";
    var keysDirectoryPath = Path.Combine(environment.ContentRootPath, keysDirectoryName);
    if (!Directory.Exists(keysDirectoryPath))
    {
        Directory.CreateDirectory(keysDirectoryPath);
    }
    services.AddDataProtection()
          .PersistKeysToFileSystem(new DirectoryInfo(keysDirectoryPath))
          .SetApplicationName("YourApplicationName");
}

From docs:

2 Comments

this should mark as Accepted Answer
is there a connection between the call to .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) and .AddCookie ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.