How to know when OWIN cookie will expire?

26,088

All you need is to get hold of the CookieValidateIdentityContext during the cookie validation stage. Once you get it, extract whatever you need and keep them as Claim or some other way that you prefer.

For MVC 5 with Asp.NET Identity 2.0, you need to perform two steps:

  1. Define custom OnValidateIdentity, extract cookie information, and keep it as Claim.

    public class Startup
    {
      public void Configuration(IAppBuilder app)
      {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
          AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
          Provider = new CookieAuthenticationProvider
          {
            OnValidateIdentity = MyCustomValidateIdentity //refer to the implementation below
          }
        }
      }
    
    
      // this method will be called on every request
      // it is also one of the few places where you can access unencrypted cookie content as CookieValidateIdentityContext
      // once you get cookie information you need, keep it as one of the Claims
      // please ignore the MyUserManager and MyUser classes, they are only for sample, you should have yours
      private static Task MyCustomValidateIdentity(CookieValidateIdentityContext context)
      {
        // validate security stamp for 'sign out everywhere'
        // here I want to verify the security stamp in every 100 seconds.
        // but I choose not to regenerate the identity cookie, so I passed in NULL 
        var stampValidator = SecurityStampValidator.OnValidateIdentity<MyUserManager<Myuser>. MyUser>(TimeSpan.FromSeconds(100), null); 
        stampValidator.Invoke(context);
    
        // here we get the cookie expiry time
        var expireUtc = context.Properties.ExpiresUtc;
    
        // add the expiry time back to cookie as one of the claims, called 'myExpireUtc'
        // to ensure that the claim has latest value, we must keep only one claim
        // otherwise we will be having multiple claims with same type but different values
        var claimType = "myExpireUtc";
        var identity = context.Identity;
        if(identity.HasClaim(c=> c.Type == claimType))
        {
          var existingClaim = identity.FindFirst(claimType);
          identity.RemoveClaim(existingClaim); 
        }
        var newClaim = new Claim(claimType, expireUtc.Value.UtcTicks.ToString());
        context.Identity.AddClaim(newClaim);
    
        return Task.FromResult(0);
      }
    }
    
  2. Access your Claim in your controller methods

    // since expiry time has now become part of your claims, you now can get it back easily
    // this example just returns the remaining time in total seconds, as a string value
    // assuming this method is part of your controller methods
    
    public string RemainingTime()
    {
      var identity = User.Identity as ClaimsIdentity;
      var claimType = "myExpireUtc";  //NOTE: must be the same key value "myExpireUtc" defined in code shown above
    
      if(identity != null && identity.HasClaim(c=> c.Type == claimType))
      { 
        var expireOn = identity.FindFirstValue(claimType); 
    
        DateTimeOffset currentUtc = DateTimeOffset.UtcNow;
        DateTimeOffset? expireUtc = new DateTimeOffset(long.Parse(expireOn), TimeSpan.Zero);
    
        var remaining = (expireUtc.Value - currentUtc).TotalSeconds;
    
        return remaining.ToString();
      }
      return string.Empty;
    }
    

I use this approach to remind my application users to extend their session before session time out.

Credit to this post How do I access Microsoft.Owin.Security.xyz OnAuthenticated context AddClaims values?

Share:
26,088

Related videos on Youtube

FrankO
Author by

FrankO

Updated on October 26, 2020

Comments

  • FrankO
    FrankO over 3 years

    I would like to create some kind of countdown timer based on the time the OWIN cookie will expire. I am using OWIN with MVC 5 and from what I understand SlidingExpiration is on by default. I do not use 'session' as I need this app to live within a web farm (I dont plan on deploying a session database).

    • FrankO
      FrankO about 10 years
      Is this not possible?
  • InTheWorldOfCodingApplications
    InTheWorldOfCodingApplications over 7 years
    Do you have a working project where this code runs? Struggling to understand what to do with ar stampValidator = SecurityStampValidator.OnValidateIdentity<MyUserManager<Myus‌​er>. MyUser>(TimeSpan.FromSeconds(100), null); as I don't have User Manager class and my User class a merely a DTO
  • mlhDev
    mlhDev over 6 years
    'I use this approach to remind my application users to extend their session before session time out.' - how do you acquire the expiration time without extending it? Perhaps related - do you have slidingexpiration enabled?
  • jgasiorowski
    jgasiorowski about 6 years
    That really helped me. But it is woth notice that stampValidator.Invoke(context); is awaitable and it should be awaited! I had nasty exception because of that ;)
  • pixelda
    pixelda over 5 years
    A great idea but for me the claims are never persisted in my implementation and not available in a controller. I have to use _userManager.AddClaim(user.Id, new Claim(i.ClaimTypeName, i.ClaimTypeValue)); to save claims. I therefore added a static list of class instances that store the values keyed on a user name. This is probably not the way to go on a web farm, but storing an encrypted record in a database is an option
  • afr0
    afr0 almost 5 years
    @phyo do you know how to extend the session expiry once it is actually expired?
  • Phyo
    Phyo almost 5 years
    @afr0 - I set SlidingExpiration to true for CookieAuthenticationOptions. Doing so will extend cookie's expiry time when user make new HTTP requests during the second half of his/her session time. But if the form-authentication-cookie is actually expired, user has to login again.
  • afr0
    afr0 almost 5 years
    @Phyo agree on that part and SlidingExpiration is true by default as well. form-authentication-cookie is that different from OWIN-Cookie? should these two be used together?
  • Ricardo Saracino
    Ricardo Saracino over 4 years
    I have a solution that takes the SlidingExpiration into account stackoverflow.com/a/59038642/338456
  • Cornel
    Cornel almost 3 years
    @Phyo why did you chose not to regenerate the identity cookie? Currently I have the following code: regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ApplicationCookie). Removing this (null) will have any impact?