简体   繁体   中英

IsAuthenticated stays true after expiry

I've been handed a requirement to force a re-authorization of a user, when a new month starts (we have a monthly subscription model). To implement this and to NOT influence other authentication providers used in our application, I've modified the sign in call as follows:

Before:

await HttpContext.SignInAsync(authorizationProvider.GetClaimsPrincipal());

After:

await HttpContext.SignInAsync(authorizationProvider.GetClaimsPrincipal(), authorizationProvider.GetAutheticationProperties());

public AuthenticationProperties GetAutheticationProperties() =>
   new AuthenticationProperties
   {
      ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(1),
      IsPersistent = true,
      AllowRefresh = false
   };

Note that ExpiresUtc is being set to 1min in the future for testing purposes; it will be computed to the end of the month once the implementation works.

I've expected that our identity (extending ClaimsIdentity ) would get its propererty IsAuthorized false after the ExpiresUtc has been reached, but it doesn't. Reading ClaimsIdentity.IsAuthenticated it states

true if the identity has been authenticated; otherwise, false. Remarks: true if the AuthenticationType property is not null or an empty string.

Now I'm confused.. What shall I expect after expiry occurred? Respectively, how does the identity become IsAuthenticated == false ?

We currently use asp.net core 2.2 and are in the process of migration to 3.

Authentication is being registered like this on application startup ( Startup.cs ):

        var expirationInMinutes = Convert.ToInt32(Configuration["Authentication:ExpirationInMinutes"]);
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                // Configure cookie authentication
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>
                                                                              {
                                                                                  o.LoginPath = new PathString("/Account/LogOn");
                                                                                  o.LogoutPath = new PathString("/Account/LogOut");
                                                                                  o.AccessDeniedPath = new PathString("/Account/AccessDenied");
                                                                                  o.SlidingExpiration = true;
                                                                                  o.ExpireTimeSpan = TimeSpan.FromMinutes(expirationInMinutes);
                                                                                  o.Cookie.Expiration = TimeSpan.FromMinutes(expirationInMinutes);
                                                                                  o.EventsType = typeof(CustomCookieAuthenticationEvents);

                                                                                  // Used because of safari
                                                                                  o.CookieManager = new ChunkingCookieManager()
                                                                                                    {
                                                                                                        ChunkSize = 2048,
                                                                                                        ThrowForPartialCookies = true
                                                                                                    };
                                                                              });

When the user is authenticated, a ticket is issued. To save on DB queries, that ticket is revalidated on an interval (20 minutes by default). When the auth ticket has expired, that won't actually take effect until the ticket is revalidated, so if your validation interval is 20 minutes, they will remain logged in for at least 20 minutes, regardless of what you set the expiration to.

You can lower this interval, all the way down to zero if you like, which effectively means the ticket would be revalidated with every request. However, the lower the interval, the more queries your DB will have to field, so it's a trade-off. To change the interval, just add:

services.Configure<SecurityStampValidatorOptions>(c =>
{
    c.ValidationInterval = TimeSpan.FromMinutes(1);
});

Another reason of not expiring on time as expected can be ClockSkew . By default your token will be valid up to 5 extra minutes.

See JWT Token authentication, expired tokens still working, .net core Web Api

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM