Your FedAuth Cookies on a Diet: IsSessionMode=true

More occult goodness for your programming pleasure! The Session Mode is a great feature of WIF which is not known as widely as it should be.

Sometimes you will be in situations in which it is advisable to limit the size of the cookie you send around. WIF already take steps for being parsimonious with the cookie size. By default, the cookie will contain just the layout defined by the SessionSecurityToken: more or less the minimal information required for being able to reconstruct the IClaimsPrincipal across requests (as opposed to a verbatim dump of the entire incoming bootstrap token, with its logorrheic XML syntax, key references & friends).

Let’s see if we can visualize the quantities at play here. If you take the FedAuth cookie generated from the default token issued from the default STS template implementation in the WIF SDK, the one with just name & role claims hardcoded in a SAML1.0 assertion, you get the following:

FedAuth 77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48U2VjdXJpdHlD b250ZXh0VG9rZW4gcDE6SWQ9Il83NTNmMzFiYi01N2QxLTQ2YzAtOWY5ZS02MTNj YTBhY2VmYWQtQkQzN0YzRTdGQUJCMzg5NTYzMEExNDUzQkEyQTlCOEUiIHhtbG 5zOnAxPSJodHRwOi8vZG9jcy5vYXNpcy1vcGVuLm9yZy93c3MvMjAwNC8wMS9vYX Npcy0yMDA0MDEtd3NzLXdzc2VjdXJpdHktdXRpbGl0eS0xLjAueHNkIiB4bWxucz0iaH R0cDovL2RvY3Mub2FzaXMtb3Blbi5vcmcvd3Mtc3gvd3Mtc2VjdXJlY29udmVyc2F0aW 9uLzIwMDUxMiIPElkZW50aWZpZXIXJuOnV1aWQ6OWQ2MzE5YmYtZTg3MC00Yz Q4LWIxNmYtNWU1MjhhYzVmMjU5PC9JZGVudGlmaWVyPjxJbnN0YW5jZT51cm46dXVpZD o3NjdmNjBmZC1jYzZmLTQ2ZWEtYjI3OC0zZGQ2MmIxYTg5NjE8L0luc3RhbmNlPjxDb2 9raWUgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwNi8wNS VFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFxYzlGQWs2YlBVRzVHY0JP bUJKTWJRQUFBQUFDQUFBQUFBQURaZ0FBd0FBQUFCQUFBQUROZndoSGJsZDJrbU g3UWcvUENPQlFBQUFBQUFTQUFBQ2dBQUFBRUFBQUFJQVF2ZCt1bGNnOFIyRXZS MytjUllHWUFnQUExNTYvR0ovLzNNNVd0Y1RNT243N0pDYlFpTHkzdkRnTjVTbzBCd XIzaVlTaUUxUnFSWjJHWVJaRGQ1UWc1YktlS0JGTjhDZi82VXhHbG1SY2Z5eU5oejlNM lY3WUFTV1lvWDl6NTZ0cnpORnVJbk9kWUJaYXhaZFF4SGs5MHZEakd1cWN1ZEdCU2 NjSGJFbmNuTHVDT01HTWJ3TEhOdzhJbEwwcDM0TlYvRS9CbGRUWWZDUkViVWd2 cU5xS3NJV2locnZHbzZYMzA1ajBMWVdqSDY0bnI4bENiU1ZiTnJEVHhJNGsvTGhOan ovZExNN3c3YkkyNGdTWHhEMXFyaEpsZDZIRVFtWTkybVJUY0Z2eGFPamlpbm1lSEN mWDJXbFB1anZEMldvcW5pb0tNZ0c4K0laL0REMlhQVjBsRU5USjlwK0R4RXdwU3htW jJCR1U1eGs3MlNZYjIxc2ovQXdNNmZGc1dacWEyUlJYK2FEZkozVzN6WUJlV1N5U3dv eSt1MjFNRUxiaDVJaTFRamJTVUxaa3IyTG1OenA4ZkpzMC94ZWNReHA0c1ovbnpsT2x CVng1ZVlHMEV5MDBVMHZDQ0poVDBHeEU3Y3JtbXFiTm00UDg1di8rSWkzNGQ2Qjh TVWkwTjFrL001aFpiRGFaejg0a2wxcXF5SzRLcmQ4eXdoT1ZtZGFsUnNpWUFUSzdTdkd xRFNxdlBYRjN2cGJ6d0d4Y0NLeGFReTdUY2hkeFNNakNEdUdLcmExNGY1U00vZUszcH JCTDlxNSsxaXVRcXpXK1JQWlIvVEMyVTdjdjRNTGhwaEhsT1FFVVlOTzYyYWljQXppQ3B qODRrOThHUW5EYWJsdlp2Rm1aaFg1TE5WUkt3QjNpZUxreGFsaiswVmJSejZoQnpTM 2JxQTB3ZHNHakpLS3Q4VjQzNXZuN2RjaVVNWk9mVlpTcWxOd1N2WnBzdHZBSTVVe XUvbVRKWit0bnM5M0ZBaXVxRHBJOXdOV3MyeE5LNXhjUDNyNms5TENEL1lHdkdhb UdDWWVPWXpjcnA1ei82b2g2K2ZSRThBSXVEOWNURHdsV2VYUVQyM3pZVU14aEFN OGtzQUttU1kyQmVmaGJM FedAuth1 U1ZBVnJFbTJ5SnhmaGtLQlQzbnJTM0pYaXNMMUx5SmFHWUxLQXlXejEwMGRoUUF BQUQ4a2l4K3Q4V0EyaVFZVkVDeGdPdk85VUVxaXc9PTwvQ29va2llPjwvU2VjdXJpdHlD b250ZXh0VG9rZW4

Slightly more than 2K. Not the nimblest thing you’ve ever seen, but not a cetacean cookie either. On the other hand we have just two claims here; what happens if we have more than those, or we have big claims such as base64’ed images or similar? Moreover: sometimes we do need to include the bootstrap token in the session, for example when we call a frontend which needs to invoke a backend acting as the caller. Let’s pick this last case: keeping the same token we used above, let’s save it in the session (by adding saveBootstrapTokens="true" to the microsoft.identityModel/service element on the RP) and see how big a cookie we get:

image

FedAuth 77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48U2VjdXJpdHl b250ZXh0VG9rZW4gcDE6SWQ9Il80YzNhMTY0NS1iMjFiLTQ5MGYtYjIwNC1iZjRkOT JhYmUyYzYtQzFFQUREMkFCRDhCMkY2RTgwNTQ4RkFFOTY0QTgwOUQiIHhtbG5 zOnAxPSJodHRwOi8vZG9jcy5vYXNpcy1vcGVuLm9yZy93c3MvMjAwNC8wMS9vY XNpcy0yMDA0MDEtd3NzLXdzc2VjdXJpdHktdXRpbGl0eS0xLjAueHNkIiB4bWxucz 0iaHR0cDovL2RvY3Mub2FzaXMtb3Blbi5vcmcvd3Mtc3gvd3Mtc2VjdXJlY29udmV yc2F0aW9uLzIwMDUxMiIElkZW50aWZpZXIXJuOnV1aWQ6ZjExODk4MWMtNWQxNC00 OTc0LThiZWItYWQ1NzA2MDg5NzUwPC9JZGVudGlmaWVyPjxJbnN0YW5jZT51cm46d XVpZDpkMzRlYzY1ZC1kOGRjLTQ3ZjQtOTNjYS01OGU3NzcxZDI4MzM8L0luc3Rhb M9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwNi8wNS9zZWN1cml0 VFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFxYzlGQWs2YlBVRzV Y0JPbUJKTWJRQUFBQUFDQUFBQUFBQURaZ0FBd0FBQUFCQUFBQUJwOU9 uaWpIWkhVZ1kzVTROdUFlZk9BQUFBQUFTQUFBQ2dBQUFBRUFBQUFCM29B N3A3V0FIOUlocm5kdXV2SFk0NENRQUEzUS9zR2tRWWY0U2VxbDZTWVJSUkd2 R1I2VjRscjVUcE9VWGY3T04rdkZSaktLc3gzc1VTSTlOYy9RQVFOb2lKK2owWFd3 ZC9yTG5Dbm9PUWY1NnpZREZsQ2ZZZnRGN3JqdjFsemJ4cVJ0OWpKdVRPUTl uaGtWNlZMc3ppdjNkV1RCMnU2TGp6YUxrSld5dURFaXVDMWVBcXhQdzUrMT FPeGZJY3p1eXgrK0hUTFFFQVEwUmdSZG5NbmlVajdBRDIzRktLeVZ4U0NoN3B HTm14Rk1RVVM2V0V6eE5KU1FlRFlxN0NUOVhvak9xZXVQLzdZU1dwTDZkRVN aUFFmTFlCaWhnNmVBVGttKzdHc1ptdFgycVNkT0tFSUtYU2dCbTZ1UVlQaEV GVUIxeS9TSDhpVVFyemNJV0tlUjNPNzFCUjVuSjdUR2dNZmlRTHMvZXFNdUVj Y0pXUFpVWGZrOVljQ1FUdWJob04yd2dhcS84TURKT3ptdHEwbExNc0NKTmlM L0JlVVdjUTMyeVQyY1F6RkdGeEVsVDZ2VXRROG1CSWJNdVlkUm0yNG1McUR XeUlNdStTbkFuMVRzUHV5MXppek5OY1VjdXJianpxb2ZPU0J3TFBndklnbFF2bH haYXRnQmE2VUZubzlHN2w1R2V6L2NFWCt3MTNaYWxaV1pWNFcwRmhwckx pR2x6S2N0cUVZMnMrcmRvd0tUNHpPZmFvS2R1UTdzcHFrSTRBMzZmMXord mk1MStKakNYbG5ReGNGRjkxVzUyd1Y4ODdRZWw5S2dTSHJ5K3BpWDBxdGRQ R0JIRGR6UE5lZlRDem1GOXZyVGhudUtwM2dRSVM3eFczdjRMQlRHNVJENmlO N2haZGJOdzlic092RVZ5cGlZUGg1a0tBUUYzbTVzeE1paFlzSGZtS08yMEhUSkMx RnJ3RjlMK2Mwck1US3RCWGhZNWJQc0E4UEVOd1Q2c3lLUjNrSVZ1cTZUS1crT HByQ1AvdUx4TEhITzRDaUtjaXdsNi9EOFdrOFFQRXF3c3RSd29EdDJiV3ByeTcw dmhjNGJxYk1RODUvZVVrYWFjVUdWUnhKSWZ3TStMNWdScHI3V3Ztd0pRKzR pY0JC FedAuth1 MUNnY2F2Qo3alZKVWlCVkF5bWozbkZhZmtBS1BhaXBvSEhxMXJrVmFkWG 9oQjA3Y0RkUWZNTnlpK1g2RGUvbkp4cnQvTTZQNVdsYkdjSEp5MW84K1pw czBaOFhkQm5VanJ1dnE2QWFrbzlndm1Zb0g0cGlqbTlvZWM2L0RQOTEvL1R hR1JWTGUyMFlwRFl3bHd4cFpERnYzMzR4bDZaK3dNUVhRVzJsUmt3THJNOG JDckdqcWVYKzg0SGV3cHNkWGhrZlBRK0l2U1Q4VlhocmI3WmlKNXRzRmFtO HFJVlg0QjB1TlUyS2IxOC9zYzRaLzEwQzEwd3NvSkhpOTVWUmZ0U1R5VmlUR CtuMjN0VmViZ2Y1bVFqRkNnOTlFQmI3RzRtdG9uTnZIVFFNalZwNUc5MkszW E5UK2pldllRaGNpSm11YktHaUYvTWVaNVhyN2pjYnNsbDNvcWU3NERkbEF lcDg5N0V3VmtvNHczL3h3REhDMHdsVTV2a0YvVHgzc3c5YWZRWlJoR3RNb Dd0U0dDOVBsa2xTeGd0SnYrUi9JL2g5b3hhV01aalF5dXNmMng2eVB6L0gwV2 ZaWXIxSVNwVFRvMjY0L2lUb2ViaTBkN1ZVR3R2NkFhUjhGd2RmWXFxelp0YT k5NzEzWHhicjVLNWdWaGhyaXFOTVplZnpncGxUcHhibEwwSnBsRmJLYXA4 aHNjTnhxWW4xZnRvV0F1WWw5WHBpeDAvWnl4YytHMGFISU5IbWRwbGpu d2pPQko5K0JRY093MllDNXc2cXBVNjd6ejNPc0gwYlBTaDRKdVFnRllwYUE0 VklLS3VJZnJMT2N3bHYvaEJwS0d3NWU1YWNWaFEvenZ3cW1reG5YZHdZVm pnUzNEbGE2Vmp2c2tmUWhNdVVSOHNGckdTbWdxdyt2cXk0WHlXYW1xem RXcHZIUjd0RUhua1J4Qmt4NFdlb3gzcFVINXlZUjM0K29wcS94b2U2d1dEcVpr RmFqV1N2d0l2UXVsZXREa2xDQmM3NWU5RU1NZmQ5eVFGcTFTNWlyNXRL QUVnV1FGUDZ5eGpadGZmc2hzWUZnM2p2dEFNZnFPN2tib0xYejR4MjJKekF 1QU9BR1ZCaXZGYW8waHFjVWNBcTl4UGdyT2xvcGR2M0luMFJqK3krR2JiL1R BaEJ0TGtrS0FzSjNBR2oyR0VMVjdoSjRHdlErVlJlY0xQNlI3R0xnN3p3T1hqeWtYc EVWZEJZb2pqS2pCeTBldmI2dkI3YmoxaXBrclAyQmRRRnkwbGZiTjVEcXY3SlU 3NXRlRXFXT01SWG5YdEwzVjRFRmUvSGNQSFJIZmx6djRPZUtuSWRjeHVrSHp rWGhUWmlwRGM4SDRXcWwvZFMvSmdnVEg5em5MRTJaakhUQUFWMSsySC 9ldTc5UDMwbHM0emwvL2cxck9sQm1ydEJzMVFFcnJ6M0pBL25PcS84RmpCW GttOVcwSXVtNDZ5TnVWOFBXOHVqNjhBODJCb0Q3TWZneUVFRVNUdUtyOU Y1WTZPWVU1bjJBTUs5RW05dW1DMDdRSmJmUjVQTTRhdzNxRjNkemc2UXU xdHhkelFTSVI4TWw1SjhkTGw1RmhCbi90bHVMOFpuTXNVTmpmWGx0RWs3 Y2NRLyt5RHdVWHZvYUpldUZKRE4yR3paZGZNeHdwTC9lOHJwbStCVlpwT3R 0M2tpdXY1L081QVZ2K3NRbzlMZUpHdHNjOGE0TkZ2MDNndHVzVS9LT25HW m0vdDQ0SFQ3OVVkSWZHZmtEaHpucjB2ZWZBRUVQZGpwWnp0dmlYQUg4c zE1TUIvcXFWS0FaU1FyMXFEekdIaldsOGpCUHhxeVAvYWVqVkU4MVRUdnBBe CtUWWNmTHg5bzZ4bzFtVEU3ZHBabWZmaUtKdEd4WE4wckNlcDhZbEpjcW5 2Zzh5K2E1VExsT0lTNm5GbElMaVdxdWxmRlNuV29LR0gzQTZTQ3JHeWp6cG9F FedAuth2 UEFRV1lOcI0OCtTK21SRjdKR2hiS1RsY3ZwK2JnTzdnMWFuWDRjQTduV3hEb WpTdWVoYWVtaXZiV1FLMHc2eEQwdkRnMkM5dmZYd1BCOW16bVYzVW1D WTR1cUcySUVXZlZoczd1NFZ6bjZzM2thNHZkTUhxSFFDdHJVRGZlOGV1N0l0S GRpMlpEaHRob2d5Mk1KeUZGeUQwRE1pbzN0VnJXTVlTclR3Mmh0WUFIMEx qYlo2cXBERUxJZllpY3JOSkloSmhZUEp0eHBPL2daV1QxWS8xQWppcmMxTTJ 5SEpuYWtXalBWWlJnV0VETVZXWXZwQSs0ZlpKQU5GaEhyYzd5aTVuNG41WE ZER2lxbk9QME1XTk5IdW1wbXVEd2JrM21JeGtkTmNyTWhhWlF6bmlNYS9Sal U2VG14TitmdDE5bWh0KzVvS01HWFBWSWZkWGw1WTNoRUdIOHBnbHlST kE3ODBidzJQQlJEUUNBbG9XYlFhSEJhaUVKMmZQQ09WYWs1U3RzaVo0M2 Y1YzZCZ3pDaStSZks0QXkzcTgvUnRzM251WWlkQXVCYk5KQm5Td2Nlb2h Lclp1YVFOZmFFdmo2ZDlvSFVDd1g1VVZUOGdwb05kS2xVVDRpSTRzMW41 aWp2Z2kweTJHcFI5c21SQlBzRmJIcHZNWVVxRkZGZjZNM3d6amR5bWd5V mxYc1JvKy8rY0RJMTAxYkxEWHZEcDlFR203a1U3NlhoR0xYcjE0bUk2N2dJT1 ByS0ttZU9mdDZiVHhNbU9FbXprc0hocUpJZkpCVllzc3cwZTllOWJmaG5jeW lISEg5VzI0TUV1ZFZDNkxMWEdmWDdBSTFRRmZzbjlYeHF1bmM4U054MDl qdlppazhGNFJBTVNXWStUNmJ5NUQ4ZE1WSWxoVXBTOGRVMXFSc1BOQm Q2VzdPOHhBY2pIQzBvdk5OOHlJVi9zVTcvRW1POWJpaHBtMndQemN3UzlV M1JEOGFubS82RG50MzAveWtsZGJpaEc4bEdQclBTQTl0aWZaSmNoVkFGaUF c1FkNlRJQTlGUU1uaVlrNGVqVklVQUFBQVd6T3RqNDA4MFV0WGlWdzhrSH dUNlk4MS9tND08L0Nvb2tpZT48L1NlY3VyaXR5Q29udGV4dFRva2VuPg== 

That’s bigger: 5K of DPAPI-packaged goodness. And it’s just 2 claims of ValueType string, you can imagine how the size could go up fast with number and size of the individual claims. On the other hand, if you need that info there is no (clean) way around it, you’ve got to ask for a token which will contain it. However that does not necessarily imply that your cookie has to grow as well. Since RTM, WIF provides you with a simple but effective way of keeping the token info in a server side cache, which means that the cookie can be as small as the reference to the cache entry that should be retrieved in the context of the current session.

WIF already had a cache for tokens, the abstract SecurityTokenCache and subclasses (such as the default implementation MruSecurityTokenCache), which is associated to the SessionSecurityTokenHandler via the config element add/sessionTokenRequirement/securityTokenCacheType (see the post about the config). The idea behind the token cache was (and is) reducing the request processing time, since retrieving the SessionSecurityToken from a cache is more efficient than reserializing it from a cookie every time.

From there, the move toward session mode is very natural. WIF RTM added a property to the SessionAuthenticationModule, IsSessionMode. When flipped to true, IsSessionMode has the effect of ensuring that the SessionSecurityToken remains in the cache for the whole duration of the session and generating a cookie which contains just a session identifier rather than the content of the session itself. The result is a very lightweight cookie! Let’s see what cookie we get in session mode:

image

ASP.NET_SessionId f1dy2w55eigyfj55fvbnpm55 FedAuth 77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48U2VjdXJ pdHlDb250ZXh0VG9rZW4gcDE6SWQ9Il8yMGEyZWVkMy1mYzFkLTQyYzEtYT JjYi1jMWJiNTEwYTA4MWItMjJGM0E5M0I2NDZDNjFEQTE0M0NBN0YxREJEO TAyNjQiIHhtbG5zOnAxPSJodHRwOi8vZG9jcy5vYXNpcy1vcGVuLm9yZy93c3 MvMjAwNC8wMS9vYXNpcy0yMDA0MDEtd3NzLXdzc2VjdXJpdHktdXRpbGl0 eS0xLjAueHNkIiB4bWxucz0iaHR0cDovL2RvY3Mub2FzaXMtb3Blbi5vcmcvd3 tc3gvd3Mtc2VjdXJlY29udmVyc2aW9uLzIwMDUxMiIPElkZW50aWZpZXIdXJu OnV1aWQ6NDE2ODIxMGMtOTYzMy00NjIwLTk5ZGItZDc0Y2YyOTY0NmVjP C9JZGVudGlmaWVyPjxJbnN0YW5jZT51cm46dXVpZDo1N2Y0Y2JmNi00MjIw LTQ2NzEtYWQxZC1lODNkNGFlYWI4YWI8L0luc3RhbmNlPjwvU2VjdXJpdHlD b250ZXh0VG9rZW4

Tiny! A meager ~650 bytes. Neat trick, eh? Now, that doesn’t mean that all of a sudden it is a good idea to use claims for moving videos around, it stil isn’t, but the session mode does decouple you from a lot of drawbacks associated to size.

The catch is that, you guessed it, the out of the box cache class is not NLB ready (hence won’t work too well on Windows Azure either). However fixing it is not hard, derive from SecurityTokenCache your own cache and use whatever NLB-friendly storage you like. I seem to recall that Hervey did give some details in his PDC talk.

But wait, I have shown you the advantages of the session mode but I neglected to tell you how to enable that on your application! It’s pretty easy: in your global.asax add

 <%@ Import Namespace="Microsoft.IdentityModel.Web" %>

<script runat="server">

      void WSFederationAuthenticationModule_SessionSecurityTokenCreated(object sender, Microsoft.IdentityModel.Web.SessionSecurityTokenCreatedEventArgs e)
    {
        FederatedAuthentication.SessionAuthenticationModule.IsSessionMode = true;
    }

Yes, it would be nice to be able to flip this from configuration; unfortunately in the current version of WIF it can’t be done. Luckily doing it from global.asax is pretty easy as well.

That’s it, your cookies are now ready for the beach season! Unfortunately I can’t say the same about myself, but there are things that cannot be solved with Visual Studio ;-)

P.S. Many thanks to Daniel Wu for a very illuminating chat on this very topic.