Home > Sample chapters

The OWIN OpenID Connect Middleware

More on sessions

Before I close this long chapter, I need to spend a minute on session management. You already know that by default, session validity will be tied to the validity specified by the token itself, unless you decouple it by setting the option UseTokenLifetime to false. When you do so, the CookieAuthenticationOptions are now in charge of session duration: ExpireTimeSpan and SlidingExpiration are the properties you want to keep an eye on.

You also know that the cookie middleware will craft sessions that contain the full ClaimsPrincipal produced from the incoming token, but as mentioned in discussing the use of SaveSignInToken, the resulting cookie size can become a problem. This issue can be addressed by saving the bulk of the session server-side and using the cookie just to keep track of a reference to the session data on the server. The cookie middleware allows you to plug in an implementation of the IAuthenticationSessionStore interface, which can be used for customizing how an AuthenticationTicket is preserved across calls. If you want to provide an alternative store for your authentication tickets, all you need to do is implement that interface and pass an instance to the cookie middleware at initialization. Here’s the interface:

public interface IAuthenticationSessionStore
{
    Task<string> StoreAsync(AuthenticationTicket ticket);
    Task RenewAsync(string key, AuthenticationTicket ticket);
    Task<AuthenticationTicket> RetrieveAsync(string key);
    Task RemoveAsync(string key);
}

That’s pretty much a CRUD interface for an AuthenticationTicket store, which you can use for any persistence technology you like. Add some logic for cleaning up old entries and keeping the store size under control, and you have your custom session store.

Considerations about I/O and latency are critical here, given that this guy will trigger every single time you receive an authenticated request. A two-level cache, where most accesses are in-memory and the persistence layer is looked up only when necessary, is one of the solutions you might want to consider.