When using the session facility in WIF (e.g. in ASP.NET with the SessionAuthenticationModule), the session token must be protected somehow. By default WIF uses the Windows built-in DPAPI mechanism.
While DPAPI is easy to use in single-server scenarios it has some shortcomings:
- DPAPI requires the IIS user profile to be loaded. This can be a problem when you don’t have admin access to IIS (e.g. in hosted scenarios like Azure Web Sites [here]).
- DPAPI only works for non load-balanced scenarios since the DPAPI key is machine specific.
One workaround was to provide a different implementation of the protection pipeline, e.g. using X.509 certificates. This wasn’t horribly hard to do but requires some custom code and setup.
In .NET 4.5 there’s a new out-of-the-box protection mechanism using the ASP.NET machine key which may be exactly the right option (for certain scenarios). But since most of you are not running .NET 4.5 – I quickly wrote an implementation of that token handler for .NET 4.0 and made it available as part of Thinktecture.IdentityModel.
To replace the built-in session token handler with the machine key based one, do this:
- Make sure your machine keys are synced when using a web farm.
- Download Thinktecture.IdentityModel (either as source code from github, or using Nuget).
- Replace the session handler in WIF config:
<securityTokenHandlers>
<remove type=“Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler,
Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35“ />
<add type=“Thinktecture.IdentityModel.Web.MachineKeySessionSecurityTokenHandler, Thinktecture.IdentityModel“ />
</securityTokenHandlers>
HTH

Hi! I tried to use MachineKeySessionSecurityTokenHandler in my solution but the Decode Method throws HttpExceprion (Error Validating Data). For test purpose a I’m debuging the solution on a local IIS. Maybe it work just on Azure or I’m doing something wrong?
Do you have a fixed machine key in config?
Pingback: Windows Azure and Cloud Computing Posts for 8/6/2012+ - Windows Azure Blog
Dominic – Without loading a certificate, is the cookie value still protected?
Not sure i understand. The cookie protection needs some sort of key to drive the crypto. Certs are one option. The machine key is another.
Hi, Just a very quick note to say a huge thank you for this post!
you’re welcome ;)
Fantastic, thought my STS was my silver bullet until I tried to use it on Azure.
Thanks Dominick. I am sort of amazed that ACS rolled out on Azure without a solution for this.
This was a massive improvement however there are still scenarios where we see problems de-crypting tokens. The scenarios are difficult to reproduce but the end result is that a token/cookie a user was using yesterday is no longer valid today. When this happens we see uncaught Cryptographic and/or Argument Exceptions from the MachineKeyTransform. I’ve added exception trapping around these scenarios in my implementation of the SessionAuthenticationModule and in the MachineKeyTransform. Basically, when I encounter Crypto exceptions, I log the user out (kill their cookies in my case) and send them back through the STS server to re-issue their session.
@Adam – but also have expiration times – might that be the reason the token from today is expired tomorrow/invalid tomorrow?
…and have a fixed machine key?
Fixed machine key and the cookies are issued as session cookies so as long as the browser is open they remain. Its difficult to tell what changed in the cookie format when this happens but in my latest occurrence I also noticed that when it errored I had 2 cookies, FedAuth and FedAuth1. After I forced a re-issuance of tokens I had 3 cookies. I wouldn’t have expected this to be a problem, its just an odd coincidence that the two things occurred at the same time.
Also session cookie have an expiration time.
Maybe we mean different things. I am using http://en.wikipedia.org/wiki/HTTP_cookie#Session_cookie which in the definition has no expiration. Is there something in the token contents that would expire? If so that would explain the problem.
Yes, indeed. The session security token inside the cookie. You need to implement sliding expiration…just google for it.
How can I have a fixed machine key?
Do I have to change somewhere in config? to my preferred key?
http://bit.ly/WXy1RD
;)
Hi Dominick, thanks for the post. I’m trying to use this code but I’m receiving the following error, I cannot realize whats going on. Do you know what the problem might be. ?
Error:
Exception of type ‘System.ArgumentException’ was thrown.
Parameter name: encodedData
StackTrace:
at System.Web.Security.MachineKey.Decode(String encodedData, MachineKeyProtection protectionOption)
at Thinktecture.IdentityModel.Web.MachineKeyCookieTransform.Decode(Byte[] encoded) in c:\projects\ationet\development\ationet\Thinktecture.IdentityModel\Web\MachineKeyCookieTransform.cs:line 16
at Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ApplyTransforms(Byte[] cookie, Boolean outbound)
at Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver)
at Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte[] token, SecurityTokenResolver tokenResolver)
at Microsoft.IdentityModel.Web.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie)
at Microsoft.IdentityModel.Web.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken)
at Microsoft.IdentityModel.Web.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs)
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
No – not sure. First time I see this. You have to debug.
I also had the same issue…it happened when I replaced the default SessionSecurityTokenHandler with the MachineKeySessionSecurityTokenHandler and it turned out to be because the session cookies were not cleared and therefore were encrypted the old way. Just clearing the cookies fix the issue for me.
- Julien