{"id":248,"date":"2013-01-28T23:00:00","date_gmt":"2013-01-29T08:00:00","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/2013\/01\/28\/running-wif-based-apps-in-windows-azure-web-sites-4\/"},"modified":"2013-03-14T19:58:02","modified_gmt":"2013-03-15T04:58:02","slug":"running-wif-based-apps-in-windows-azure-web-sites-4","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2013\/01\/28\/running-wif-based-apps-in-windows-azure-web-sites-4\/","title":{"rendered":"Running WIF Based Apps in Windows Azure Web Sites"},"content":{"rendered":"<p>It\u2019s official: I am getting old. I was ab-so-lu-te-ly convinced I already blogged about this, but after the nth time I got asked about this I came to find the link to the post only to find pneumatic vacuum in its place. No joy on the draft folder either\u2026 oh well, this won\u2019t take too long to (re?)write anyway. Moreover: in a rather anticlimactic move, I am going to give away the solution right at the beginning of the post.<\/p>\n<h1>Straight to the Point<\/h1>\n<p>In order to run in Windows Azure Web Sites a Web application which uses WIF for handling authentication, you must change the default cookie protection method (DPAPI, not available on Windows Azure Web Sites) to something that will work in a farmed environment and with the IIS\u2019 user profile load turned off. Sounds like Klingon? Here there\u2019s some practical advice:<\/p>\n<ul>\n<li>If you are using the <a href=\"http:\/\/blogs.msdn.com\/b\/vbertocci\/archive\/2012\/10\/23\/windows-identity-foundation-tools-for-visual-studio-2012-rtm.aspx\">Identity and Access Tools for VS2012<\/a>, just go to the Configuration tab and check the box \u201cEnable Web farm ready cookies\u201d <\/li>\n<li>If you want to do things by hand, add the following code snippet in your system.identitymodel\/identityConfiguration element:<\/li>\n<\/ul>\n<div class=\"csharpcode\">\n<pre><span class=\"lnum\">   1:  <\/span><span class=\"kwrd\">&lt;<\/span><span class=\"html\">securityTokenHandlers<\/span><span class=\"kwrd\">&gt;<\/span><\/pre>\n<pre><span class=\"lnum\">   2:  <\/span>   <span class=\"kwrd\">&lt;<\/span><span class=\"html\">add<\/span> <span class=\"attr\">type<\/span><span class=\"kwrd\">=&quot;System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler,  <br \/>             System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&quot;<\/span> <span class=\"kwrd\">\/&gt;<\/span><\/pre>\n<pre><span class=\"lnum\">   3:  <\/span>   <span class=\"kwrd\">&lt;<\/span><span class=\"html\">remove<\/span> <span class=\"attr\">type<\/span><span class=\"kwrd\">=&quot;System.IdentityModel.Tokens.SessionSecurityTokenHandler, <br \/>             System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&quot;<\/span> <span class=\"kwrd\">\/&gt;<\/span><\/pre>\n<pre><span class=\"lnum\">   4:  <\/span><span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">securityTokenHandlers<\/span><span class=\"kwrd\">&gt;<\/span><\/pre>\n<\/div>\n<p>I know, it\u2019s clipped and wrapped badly: eventually I\u2019ll change the blog theme. For the time being, you can copy &amp; paste to see the entire thing.<\/p>\n<p>Note, the above is viable only if you are targeting .NET 4.5 as it takes advantage of a new feature introduced only in the latest version. If you are on .NET 4.0 WIF 1.0 offers you the necessary extensibility points to reproduce the same capability (more details below) however there\u2019s nothing ready out of the box (you could however take a look at the code that <a href=\"leastprivilege.com\/\">Dominick<\/a> already nicely wrote for you <a href=\"https:\/\/github.com\/thinktecture\/Thinktecture.IdentityModel.40\/blob\/master\/IdentityModel\/Thinktecture.IdentityModel\/Tokens\/MachineKeySessionSecurityTokenHandler.cs\">here<\/a>).<\/p>\n<p>Now that I laid down the main point, in the next section I\u2019ll shoot the emergency flare that will lead your search engine query here.<\/p>\n<h1>Again, Adagio<\/h1>\n<p>Let\u2019s go through a full cycle of create a WIF app -&gt; deploy it in Windows Azure Web Sites \u2013&gt; watch it fail \u2013&gt; fix it \u2013&gt; verify that it works.<\/p>\n<p>Fire up VS2012, create a web project (I named mine \u201cAlphaScorpiiWebApp\u201d, let\u2019s see who gets the reference ;-)) and run the <a href=\"http:\/\/blogs.msdn.com\/b\/vbertocci\/archive\/2012\/10\/23\/windows-identity-foundation-tools-for-visual-studio-2012-rtm.aspx\">Identity and Access Tools<\/a> on it. For the purpose of the tutorial you can pick the local development STS option. Hit F5, and verify that things work as expected (== the Web app will greet you as \u2018Terry\u2019).<\/p>\n<p>Did it work? Excellent. Let\u2019s try to publish to Windows Azure Web Site and see what happens. But before we hit Publish, we need to adjust a couple of things. Namely, we need to ensure that the application will communicate to the local development STS the address it will have in Windows Azure Web Sites, rather than the one on localhost:&lt;port&gt; automatically assigned (ah, please remind me to do a post about realm vs. network addresses). That\u2019s pretty easy: go back to the <a href=\"http:\/\/blogs.msdn.com\/b\/vbertocci\/archive\/2012\/10\/23\/windows-identity-foundation-tools-for-visual-studio-2012-rtm.aspx\">Identity &amp; Access tool<\/a>, head to the Configure tab, and paste in the Realm and Audience fields the URL of your target Web Site. <\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/1781.image_5F00_5316A090.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/1781.image_5F00_5316A090.png\" width=\"500\" height=\"453\" \/><\/a> <\/p>\n<p>Given what we know,&#160; we better turn off the custom errors before publishing (usual &lt;customErrors mode=&quot;Off&quot;&gt;under system.web).<\/p>\n<p>Done that, go ahead and publish. My favorite route is through the Publish\u2026 entry in the Solution Explorer, I have a .PublishSettings file I import every time. Ah, don\u2019t forget to check the option \u201cRemove additional files at destination\u201d.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2043.image_5F00_523E3AA6.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2043.image_5F00_523E3AA6.png\" width=\"500\" height=\"387\" \/><\/a> <\/p>\n<\/p>\n<p>Ready? Hit Publish and see what happens.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2867.image_5F00_78A01DF1.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2867.image_5F00_78A01DF1.png\" width=\"500\" height=\"388\" \/><\/a> <\/p>\n<\/p>\n<p>Boom! As expected, the authentication fails. Let me paste the error message here, for the search engines\u2019 benefit.<\/p>\n<table cellspacing=\"0\" cellpadding=\"2\" width=\"100%\" border=\"1\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"100%\">\n<h3>Server Error in &#8216;\/&#8217; Application. <\/p>\n<hr size=\"1\" width=\"100%\" \/><\/h3>\n<h4><i>The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread&#8217;s user context, which may be the case when the thread is impersonating.<\/i><\/h4>\n<p>        <b>Description: <\/b>An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. <\/p>\n<p><b>Exception Details: <\/b>System.Security.Cryptography.CryptographicException: The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread&#8217;s user context, which may be the case when the thread is impersonating. <\/p>\n<p><b>Source Error:<\/b> <\/p>\n<p><code>An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.<\/code><\/p>\n<p><b>Stack Trace:<\/b><\/p>\n<p><code><\/code><\/p>\n<p>        <code><\/p>\n<pre>[CryptographicException: The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating.]\n   System.Security.Cryptography.ProtectedData.Protect(Byte[] userData, Byte[] optionalEntropy, DataProtectionScope scope) +379\n   System.IdentityModel.ProtectedDataCookieTransform.Encode(Byte[] value) +52\n\n[InvalidOperationException: ID1074: A CryptographicException occurred when attempting to encrypt the cookie using the ProtectedData API (see inner exception for details). If you are using IIS 7.5, this could be due to the loadUserProfile setting on the Application Pool being set to false. ]\n   System.IdentityModel.ProtectedDataCookieTransform.Encode(Byte[] value) +167\n   System.IdentityModel.Tokens.SessionSecurityTokenHandler.ApplyTransforms(Byte[] cookie, Boolean outbound) +57\n   System.IdentityModel.Tokens.SessionSecurityTokenHandler.WriteToken(XmlWriter writer, SecurityToken token) +658\n   System.IdentityModel.Tokens.SessionSecurityTokenHandler.WriteToken(SessionSecurityToken sessionToken) +86\n   System.IdentityModel.Services.SessionAuthenticationModule.WriteSessionTokenToCookie(SessionSecurityToken sessionToken) +148\n   System.IdentityModel.Services.SessionAuthenticationModule.AuthenticateSessionSecurityToken(SessionSecurityToken sessionToken, Boolean writeCookie) +81\n   System.IdentityModel.Services.WSFederationAuthenticationModule.SetPrincipalAndWriteSessionToken(SessionSecurityToken sessionToken, Boolean isSession) +217\n   System.IdentityModel.Services.WSFederationAuthenticationModule.SignInWithResponseMessage(HttpRequestBase request) +830\n   System.IdentityModel.Services.WSFederationAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs args) +364\n   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136\n   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp; completedSynchronously) +69\n          <\/pre>\n<p>        <\/code><\/p>\n<hr size=\"1\" width=\"100%\" \/><b>Version Information:<\/b> Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.17929 <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>What happened, exactly? It\u2019s a well-documented phenomenon. By default, WIF protects cookies using DPAPI and the user store. When your app is hosted in IIS, its AppPool must have a specific option enabled (\u201cLoad User Profile\u201d) in order for DPAPI to access the user store. In Windows Azure Web Sites, that option is off (with good reasons, it can exact a heavy toll on memory) and you can\u2019t turn it on. But hey, guess what: even if you could, that would be a bad idea anyway. The default cookie protection mechanism is not suitable for load balanced scenarios, given that every node in the farm will have a different key: that means that a cookie protected by one node would be unreadable from the other, breaking havoc with your Web app session.<\/p>\n<p>What to do? In the training kit for WIF 1.0 we provided custom code for protecting cookies using the SSL certificate of the web application (which you need to have anyway) \u2013 however that is an approach more apt to the cloud services (where you have full control of your certs) rather than WA Web Sites (where you don\u2019t). Other drawbacks included the sheer amount of custom (code required (not staggering, but non-zero either), its complexity (still crypto) and the impossibility of making it fully boilerplate (it had to refer to the coordinates of the certificate of choice).<br \/>\n  <br \/>In WIF 4.5 we wanted to support this scenario out of the box, without requiring any custom code. For that reason, we introduced a cookie transform class that takes advantage of the MachineKey, and all it needs to opt in is a pure boilerplate snippet to be added in the web.config. Sometimes I am asked why we didn&#8217;t change that to be the default, to which I usually answer: I have people waiting for me at the cafeterias to yell at me for having moved classes under different namespaces (sorry, that\u2019s the very definition of \u201cmoving WIF into the framework\u201d :-)), now just imagine what would have happened if we would have changed the defaults :-D.<\/p>\n<p>More seriously: you already know what the fix is: it\u2019s one of the two methods described in the \u201cStraight to the Point\u201d section. Apply one of those, then re-publish. You\u2019ll be greeted by the following:<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/3021.image_5F00_170A5EDB.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/3021.image_5F00_170A5EDB.png\" width=\"500\" height=\"359\" \/><\/a> <\/p>\n<p>We are Terry again, but this time, as you might notice in the address bar\u2026 in the cloud!<\/p>\n<p>&#160;<\/p>\n<p>&#160;<\/p>\n<p>Alrighty, hopefully that was pretty straightforward. As usual, have fun!<\/p>\n<div style=\"clear:both\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>It\u2019s official: I am getting old. I was ab-so-lu-te-ly convinced I already blogged about this, but after the nth time I got asked about this I came to find the link to the post only to find pneumatic vacuum in its place. No joy on the draft folder either\u2026 oh well, this won\u2019t&#8230;<\/p>\n","protected":false},"author":1,"featured_media":1301,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"categories":[5,6,4],"tags":[],"class_list":["post-248","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-wif","category-windows-azure","category-windows-identity-foundation"],"_links":{"self":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/248","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/comments?post=248"}],"version-history":[{"count":2,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/248\/revisions"}],"predecessor-version":[{"id":1660,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/248\/revisions\/1660"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/1301"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=248"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=248"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=248"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}