The WIF runtime provides a nice feature named Session Mode. When set to true
, it allows the security tokens to be cached to the server. This feature is particularly useful if you are dealing with the large set of claims in the token. In this recipe, we will explore the steps to enable WIF Session Mode in an ASP.NET Web Application and write a SecurityTokenCache(Microsoft.IdentityModel.Tokens)
implementation that allows the tokens to be stored in Memcached distributed cache.
If you are not familiar with the Memcached distributed cache, you can learn more about it in the First round playing with Memcached article by Shaun Xu at http://geekswithblogs.net/shaunxu/archive/2010/04/07/first-round-playing-with-memcached.aspx.
You can download memcached.exe
from http://www.splinedancer.com/memcached-win32/memcached-1.2.4-Win32-Preview-20080309_bin.zip and follow the steps specified in the article to configure the distributed cache in an ASP.NET Web Application.
To enable WIF Session Mode and create custom SecurityTokenCache
, perform the following steps:
SessionSecurityTokenCache
. Use the Federation Utility wizard tool to create an STS reference. SessionSecurityTokenCache
project for Memcached support by referring to the article mentioned under the Getting ready section. Global.asax.cs
file, and implement a handler for the SessionSecurityTokenCreated
event:void WSFederationAuthenticationModule_SessionSecurityTokenCreated(object sender, Microsoft.IdentityModel.Web.SessionSecurityTokenCreatedEventArgs e) { FederatedAuthentication.SessionAuthenticationModule. IsSessionMode = true; }
Inside the event handler, set the SessionAuthenticationModule.IsSessionMode
to true.
MemCachedSecurityTokenCache
class and implement the SecurityTokenCache
abstract class. Use the implementation to store SecurityToken
in the Memcached distributed cache:public class MemCachedSecurityTokenCache : SecurityTokenCache { private object _syncRoot; public MemCachedSecurityTokenCache() { this._syncRoot = new object(); } public override void ClearEntries() { lock (this._syncRoot) { DistCache.RemoveAll(); } } public override bool TryAddEntry(object key, System.IdentityModel.Tokens.SecurityToken value) { bool flag; lock (this._syncRoot) { SecurityToken token; flag = this.TryGetEntry(key, out token); if (!flag) { DistCache.Add(key.ToString(), value); } } return !flag; } public override bool TryGetAllEntries(object key, out IList<System.IdentityModel.Tokens.SecurityToken> tokens) { //TODO: No implementation necessary for the sample tokens = new List<SecurityToken>(); return true; } public override bool TryGetEntry(object key, out System.IdentityModel.Tokens.SecurityToken value) { bool flag = false; lock (this._syncRoot) { value = DistCache.Get(key.ToString()) as SecurityToken; if (value != null) flag = true; } return flag; } public override bool TryRemoveAllEntries(object key) { if (key != null) { lock (this._syncRoot) { DistCache.RemoveAll(); return true; } } return false; } public override bool TryRemoveEntry(object key) { if (key != null) { lock (this._syncRoot) { SecurityToken entry; if (TryGetEntry(key, out entry)) { DistCache.Remove(key.ToString()); return true; } } } return false; } public override bool TryReplaceEntry(object key, System.IdentityModel.Tokens.SecurityToken newValue) { lock (this._syncRoot) { return (this.TryRemoveEntry(key) && this.TryAddEntry(key, newValue)); } } }
Microsoft.IdentityModel
section in the Web.config
file, use the<securityTokenHandlers>
element to register the distributed SecurityTokenCache
implementation:<securityTokenHandlers> <add type="Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"> <sessionTokenRequirement securityTokenCacheType="SessionSecurityTokenCache.MemCachedSecurityTokenCache, SessionSecurityTokenCache"/> </add> </securityTokenHandlers>
The WSFederationAuthenticationModule
HTTP module triggers the SessionSecurityTokenCreated
event. The handler allows us to enable the WIF Session Mode. The SecurityTokenCache
implementation is then used to store the issued tokens in a distributed cache. Now, the cookie only stores the session identifier, which is very lightweight, so the cost of re-serializing the cookie every time is saved.
The WIF runtime provides an implementation of SecurityTokenCache
named as MRUSecurityTokenCache
that accommodates new tokens by removing the least recently accessed item.