How to know when OWIN cookie will expire?

.net, asp.net-mvc-5, owin, session-cookies

Solution

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:

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);
  }
}

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?

Problem

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).

Original source

Related problems