How to handle cookie expiration in asp.net core

三世轮回 提交于 2019-12-03 16:17:59

Looks like you need your own handler for OnValidatePrincipal event when setuping cokies auth middleware:

OnValidatePrincipal event can be used to intercept and override validation of the cookie identity

app.UseCookieAuthentication(options =>
{
    options.Events = new CookieAuthenticationEvents
    {
        OnValidatePrincipal = <your event handler>
    };
});

Documentation contains example of such handle:

public static class LastChangedValidator
{
    public static async Task ValidateAsync(CookieValidatePrincipalContext context)
    {
        // Pull database from registered DI services.
        var userRepository = context.HttpContext.RequestServices.GetRequiredService<IUserRepository>();
        var userPrincipal = context.Principal;

        // Look for the last changed claim.
        string lastChanged;
        lastChanged = (from c in userPrincipal.Claims
                       where c.Type == "LastUpdated"
                       select c.Value).FirstOrDefault();

        if (string.IsNullOrEmpty(lastChanged) ||
            !userRepository.ValidateLastChanged(userPrincipal, lastChanged))
        {
            context.RejectPrincipal();
            await context.HttpContext.Authentication.SignOutAsync("MyCookieMiddlewareInstance");
        }
    }
}

There isn't a good way to accomplish this. If the cookie is expired, it is not sent to the server to extract any information. With ASP.Net Core Identity, you don't have much control over that. That leaves you to using Cookie Middleware.

This provides a user to a normal redirect when the cookie is expired:

public void ConfigureServices(IServiceCollection services)
{       
    services.Configure<CookieAuthenticationOptions>(options =>
    {
        options.LoginPath = new PathString("/Home/Index");
    });
}

The best way to achieve what you're looking for is to set the cookie expiration much later than the true user session expiration, and then perform your session expiration server side and redirect the user at that point. While it's not ideal, you don't have other options when a cookie is expired.

public void ConfigureServices(IServiceCollection services)
{
    app.UseCookieAuthentication(new CookieAuthenticationOptions()
    {
        AuthenticationScheme = "MyCookieMiddlewareInstance",
        // Redirect when cookie expired or not present
        LoginPath = new PathString("/Account/Unauthorized/"),
        AutomaticAuthenticate = true,
        // never expire cookie
        ExpireTimeSpan = TimeSpan.MaxValue,
        Events = new CookieAuthenticationEvents()
        {
            // in custom function set the session expiration
            // via the DB and reset it everytime this is called
            // if the session is still active
            // otherwise, you can redirect if it's invalid
            OnValidatePrincipal = <custom function here>
        }
    });
}

It seems there is no event for your case but you can use OnRedirectToLogin to change redirect uri. Here is an example:

OnRedirectToLogin = async (context) =>
{
      var binding = context.HttpContext.Features.Get<ITlsTokenBindingFeature>()?.GetProvidedTokenBindingId();
      var tlsTokenBinding = binding == null ? null : Convert.ToBase64String(binding);
      var cookie = context.Options.CookieManager.GetRequestCookie(context.HttpContext, context.Options.CookieName);
      if (cookie != null)
      {
            var ticket = context.Options.TicketDataFormat.Unprotect(cookie, tlsTokenBinding);

            var expiresUtc = ticket.Properties.ExpiresUtc;
            var currentUtc = context.Options.SystemClock.UtcNow;
            if (expiresUtc != null && expiresUtc.Value < currentUtc)
            {
                  context.RedirectUri += "&p1=yourparameter";
            }
       }
       context.HttpContext.Response.Redirect(context.RedirectUri);

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!