<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4134530225370527924</id><updated>2024-09-08T08:53:12.070-07:00</updated><category term=".net"/><category term="asp.net mvc"/><category term="asp.net"/><category term="padding oracle"/><category term="security"/><category term="c#"/><category term="captcha"/><category term="hmac"/><category term="html"/><category term="javascript"/><category term="jquery"/><category term="recaptcha"/><category term="amazon"/><category term="aws"/><category term="blog"/><category term="blogger"/><category term="centos"/><category term="digg"/><category term="dotnetkicks"/><category term="dotnetshoutout"/><category term="dzone"/><category term="ec2"/><category term="form"/><category term="google buzz"/><category term="hacker news"/><category term="linode"/><category term="linux"/><category term="nupack"/><category term="php"/><category term="powershell"/><category term="putty"/><category term="reddit"/><category term="rsync"/><category term="scp"/><category term="sharepoint"/><category term="ssh"/><category term="visual studio"/><category term="yahoo buzz"/><title type='text'>Eglasius</title><subtitle type='html'>coding instinct &lt;br&gt;&#xa;by Freddy Rios</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-5703348761325234838</id><published>2011-09-18T15:48:00.001-07:00</published><updated>2011-09-18T15:48:34.848-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="asp.net"/><category scheme="http://www.blogger.com/atom/ns#" term="asp.net mvc"/><category scheme="http://www.blogger.com/atom/ns#" term="c#"/><title type='text'>Using cookies to control return page after login on asp.net mvc 3</title><content type='html'>&lt;h3&gt;Default behavior and the scenario&lt;/h3&gt; &lt;p&gt;On asp.net in general, when an user tries to access a page that requires the user to login first, it is fairly common to use the built in support to return to that page after the user logins. &lt;/p&gt; &lt;p&gt;When an user tries to access the page and an authorization made by the code determines the user doesn’t have access, a 401 is returned by that code. When that happens the FormsAuthenticationModule intercepts it and instead redirects the user to the login page configured in the asp.net config.&lt;/p&gt; &lt;p&gt;When the redirect to the login page is sent,&amp;nbsp; it includes a returnUrl query string parameter. On a successful the user is sent back to that url. If no return url is indicated, the user is sent to a default url after authentication.&lt;/p&gt; &lt;p&gt;The above works fine, if the scenario fits well with the site. &lt;/p&gt; &lt;p&gt;One consideration is with the use of register and forgot password options, in which case extra code needs to be put in place if you want the user to be redirected to the url visited when the process started. A similar case is if the user visits any other page linked there, like a faq or about page and then hitting the login option you almost certainly have in your master page/layout.&lt;/p&gt; &lt;p&gt;Another consideration comes with the user of ajax based login forms accessible anywhere on the site. Depending on the site, the user might be on a page where you don’t want it redirect to. You still might want it redirected to a page the user visited before doing some action, like in a client’s scenario, a specific deal page.&lt;/p&gt; &lt;h3&gt;The cookie based approach&lt;/h3&gt; &lt;p&gt;One way to handle the above scenario is by storing the returnUrl in a cookie. By doing so the user can visit other pages (like the register/forgot password options), and the redirect will go to the last relevant page. Additionally you can control which actions are considered relevant pages, in case the user uses the login option in your master page/layout in any random page they happen to be at.&lt;/p&gt; &lt;p&gt;To set the cookie in an unauthorized access scenario, one could use a module based approach just like the &lt;em&gt;FormsAuthenticationModule&lt;/em&gt;. In our case, we instead introduced an &lt;em&gt;AuthorizeWithReturnCookieAttribute&lt;/em&gt;, and replaced the use of &lt;em&gt;[Authorize]&lt;/em&gt; with &lt;em&gt;[AuthorizeWithReturnCookie]&lt;/em&gt;.&lt;/p&gt; &lt;div style=&quot;border-bottom: #000080 1px solid; border-left: #000080 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; color: #000; font-size: 10pt; border-top: #000080 1px solid; border-right: #000080 1px solid&quot;&gt; &lt;div style=&quot;background: #fff; overflow: auto&quot;&gt; &lt;ol style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 5px; padding-right: 0px; white-space: nowrap; background: #ffffff; padding-top: 0px&quot; start=&quot;5&quot;&gt; &lt;li&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #2b91af&quot;&gt;AuthorizeWithReturnCookieAttribute&lt;/span&gt; : &lt;span style=&quot;color: #2b91af&quot;&gt;AuthorizeAttribute&lt;/span&gt;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;{  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;protected&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;void&lt;/span&gt; HandleUnauthorizedRequest(&lt;span style=&quot;color: #2b91af&quot;&gt;AuthorizationContext&lt;/span&gt; filterContext)  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;var&lt;/span&gt; ctx = filterContext.HttpContext;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #2b91af&quot;&gt;NavigationCookies&lt;/span&gt;.SetReturnAfterAuthenticationUrl(ctx, ctx.Request.RawUrl);  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;base&lt;/span&gt;.HandleUnauthorizedRequest(filterContext);  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;li&gt;} &lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;To set the cookie when a relevant page was visisted, we introduced a separate attribute &lt;em&gt;ReturnAfterAuthenticationAttribute&lt;/em&gt;. Unlike the authorize attribute, this one is used on public pages, we want the user redirected back to if the login option in the master page/layout is used.&lt;/p&gt; &lt;div style=&quot;border-bottom: #000080 1px solid; border-left: #000080 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; color: #000; font-size: 10pt; border-top: #000080 1px solid; border-right: #000080 1px solid&quot;&gt; &lt;div style=&quot;background: #fff; overflow: auto&quot;&gt; &lt;ol style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 5px; padding-right: 0px; white-space: nowrap; background: #ffffff; padding-top: 0px&quot; start=&quot;17&quot;&gt; &lt;li&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #2b91af&quot;&gt;ReturnAfterAuthenticationAttribute&lt;/span&gt; : &lt;span style=&quot;color: #2b91af&quot;&gt;ActionFilterAttribute&lt;/span&gt;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;{  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt; ViewDataIgnoreKey = &lt;span style=&quot;color: #a31515&quot;&gt;&quot;IgnoreReturnAfterAuthentication&quot;&lt;/span&gt;;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;void&lt;/span&gt; OnActionExecuted(&lt;span style=&quot;color: #2b91af&quot;&gt;ActionExecutedContext&lt;/span&gt; filterContext)  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;var&lt;/span&gt; ctx = filterContext.HttpContext;  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;if&lt;/span&gt; ((&lt;span style=&quot;color: #0000ff&quot;&gt;bool&lt;/span&gt;?)filterContext.Controller.ViewData[ViewDataIgnoreKey] == &lt;span style=&quot;color: #0000ff&quot;&gt;true&lt;/span&gt;) &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt;;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;if&lt;/span&gt; (ctx.User.Identity.IsAuthenticated) &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt;;  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;if&lt;/span&gt; (filterContext.HttpContext.Request.HttpMethod != &lt;span style=&quot;color: #a31515&quot;&gt;&quot;GET&quot;&lt;/span&gt;) &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt;;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #2b91af&quot;&gt;NavigationCookies&lt;/span&gt;.SetReturnAfterAuthenticationUrl(ctx, ctx.Request.RawUrl);  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;li style=&quot;background: #f3f3f3&quot;&gt;} &lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;There are a few more things going on in the above attribute. &lt;/p&gt; &lt;ul&gt; &lt;li&gt;We can avoid it being set based on logic executed in the action method, by setting true on the corresponding value in ViewData. In retrospective ctx.Items is probably the right place for it.  &lt;li&gt;No point in setting the cookie if the user is already authenticated.  &lt;li&gt;Post requests are not tracked.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;For a more complete sample, the modified logon and register methods of the asp.net mvc template below. It still supports the returnUrl and gives it precendence (not what we did in our case, as we only use the cookie one).&lt;/p&gt; &lt;div style=&quot;border-bottom: #000080 1px solid; border-left: #000080 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; color: #000; font-size: 10pt; border-top: #000080 1px solid; border-right: #000080 1px solid&quot;&gt; &lt;div style=&quot;background: #fff; overflow: auto&quot;&gt; &lt;ol style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 5px; padding-right: 0px; white-space: nowrap; background: #ffffff; padding-top: 0px&quot; start=&quot;23&quot;&gt; &lt;li&gt;[&lt;span style=&quot;color: #2b91af&quot;&gt;HttpPost&lt;/span&gt;]  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #2b91af&quot;&gt;ActionResult&lt;/span&gt; LogOn(&lt;span style=&quot;color: #2b91af&quot;&gt;LogOnModel&lt;/span&gt; model, &lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt; returnUrl)  &lt;li&gt;{  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;if&lt;/span&gt; (ModelState.IsValid)  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;if&lt;/span&gt; (&lt;span style=&quot;color: #2b91af&quot;&gt;Membership&lt;/span&gt;.ValidateUser(model.UserName, model.Password))  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt; SetAuthCookieAndRedirect(model.UserName, model.RememberMe, returnUrl);  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ModelState.AddModelError(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a31515&quot;&gt;&quot;The user name or password provided is incorrect.&quot;&lt;/span&gt;);  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #008000&quot;&gt;// If we got this far, something failed, redisplay form&lt;/span&gt;  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt; View(model);  &lt;li style=&quot;background: #f3f3f3&quot;&gt;} &lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt; &lt;div style=&quot;border-bottom: #000080 1px solid; border-left: #000080 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; color: #000; font-size: 10pt; border-top: #000080 1px solid; border-right: #000080 1px solid&quot;&gt; &lt;div style=&quot;background: #fff; overflow: auto&quot;&gt; &lt;ol style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 5px; padding-right: 0px; white-space: nowrap; background: #ffffff; padding-top: 0px&quot; start=&quot;57&quot;&gt; &lt;li&gt;[&lt;span style=&quot;color: #2b91af&quot;&gt;HttpPost&lt;/span&gt;]  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #2b91af&quot;&gt;ActionResult&lt;/span&gt; Register(&lt;span style=&quot;color: #2b91af&quot;&gt;RegisterModel&lt;/span&gt; model)  &lt;li&gt;{  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;if&lt;/span&gt; (ModelState.IsValid)  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #008000&quot;&gt;// Attempt to register the user&lt;/span&gt;  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #2b91af&quot;&gt;MembershipCreateStatus&lt;/span&gt; createStatus;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #2b91af&quot;&gt;Membership&lt;/span&gt;.CreateUser(model.UserName, model.Password, model.Email, &lt;span style=&quot;color: #0000ff&quot;&gt;null&lt;/span&gt;, &lt;span style=&quot;color: #0000ff&quot;&gt;null&lt;/span&gt;, &lt;span style=&quot;color: #0000ff&quot;&gt;true&lt;/span&gt;, &lt;span style=&quot;color: #0000ff&quot;&gt;null&lt;/span&gt;, &lt;span style=&quot;color: #0000ff&quot;&gt;out&lt;/span&gt; createStatus);  &lt;li&gt;&amp;nbsp; &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;if&lt;/span&gt; (createStatus == &lt;span style=&quot;color: #2b91af&quot;&gt;MembershipCreateStatus&lt;/span&gt;.Success)  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt; SetAuthCookieAndRedirect(model.UserName);  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ModelState.AddModelError(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;&quot;&lt;/span&gt;, ErrorCodeToString(createStatus));  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #008000&quot;&gt;// If we got this far, something failed, redisplay form&lt;/span&gt;  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt; View(model);  &lt;li style=&quot;background: #f3f3f3&quot;&gt;} &lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt; &lt;div style=&quot;border-bottom: #000080 1px solid; border-left: #000080 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; color: #000; font-size: 10pt; border-top: #000080 1px solid; border-right: #000080 1px solid&quot;&gt; &lt;div style=&quot;background: #fff; overflow: auto&quot;&gt; &lt;ol style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 5px; padding-right: 0px; white-space: nowrap; background: #ffffff; padding-top: 0px&quot; start=&quot;127&quot;&gt; &lt;li&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;ActionResult&lt;/span&gt; SetAuthCookieAndRedirect(&lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt; userName, &lt;span style=&quot;color: #0000ff&quot;&gt;bool&lt;/span&gt; createPersistentCookie=&lt;span style=&quot;color: #0000ff&quot;&gt;false&lt;/span&gt;, &lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt; returnUrl=&lt;span style=&quot;color: #0000ff&quot;&gt;null&lt;/span&gt;)  &lt;li style=&quot;background: #f3f3f3&quot;&gt;{  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #2b91af&quot;&gt;FormsAuthentication&lt;/span&gt;.SetAuthCookie(userName, createPersistentCookie);  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;var&lt;/span&gt; url = IsValidReturnUrl(returnUrl) ?  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; returnUrl :  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #2b91af&quot;&gt;NavigationCookies&lt;/span&gt;.GetReturnAfterAuthenticationUrl(Request);  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;if&lt;/span&gt; (&lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt;.IsNullOrEmpty(url)) &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt; RedirectToAction(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;Index&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a31515&quot;&gt;&quot;Home&quot;&lt;/span&gt;);  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #2b91af&quot;&gt;RedirectResult&lt;/span&gt;(url);  &lt;li&gt;}  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;bool&lt;/span&gt; IsValidReturnUrl(&lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt; returnUrl)  &lt;li&gt;{  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt; Url.IsLocalUrl(returnUrl) &amp;amp;&amp;amp; returnUrl.Length &amp;gt; 1 &amp;amp;&amp;amp; returnUrl.StartsWith(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;/&quot;&lt;/span&gt;)  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;&amp;amp; !returnUrl.StartsWith(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;//&quot;&lt;/span&gt;) &amp;amp;&amp;amp; !returnUrl.StartsWith(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;/\\&quot;&lt;/span&gt;);  &lt;li style=&quot;background: #f3f3f3&quot;&gt;} &lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;The &lt;em&gt;NavigationCookies &lt;/em&gt;class just sets/gets the cookie:&lt;/p&gt; &lt;div style=&quot;border-bottom: #000080 1px solid; border-left: #000080 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; color: #000; font-size: 10pt; border-top: #000080 1px solid; border-right: #000080 1px solid&quot;&gt; &lt;div style=&quot;background: #fff; overflow: auto&quot;&gt; &lt;ol style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 5px; padding-right: 0px; white-space: nowrap; background: #ffffff; padding-top: 0px&quot; start=&quot;6&quot;&gt; &lt;li&gt;&lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #2b91af&quot;&gt;NavigationCookies&lt;/span&gt;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;{  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt; ReturnAfterAuthenticationKey = &lt;span style=&quot;color: #a31515&quot;&gt;&quot;ReturnAfterAuthentication&quot;&lt;/span&gt;;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;void&lt;/span&gt; SetReturnAfterAuthenticationUrl(&lt;span style=&quot;color: #2b91af&quot;&gt;HttpContextBase&lt;/span&gt; context, &lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt; url)  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; url = &lt;span style=&quot;color: #2b91af&quot;&gt;VirtualPathUtility&lt;/span&gt;.ToAbsolute(url, context.Request.ApplicationPath);  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;var&lt;/span&gt; cookie = context.Response.Cookies[ReturnAfterAuthenticationKey];  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cookie.Expires = &lt;span style=&quot;color: #2b91af&quot;&gt;DateTime&lt;/span&gt;.Now.AddDays(1);  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cookie.Value = url;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt; GetReturnAfterAuthenticationUrl(&lt;span style=&quot;color: #2b91af&quot;&gt;HttpRequestBase&lt;/span&gt; request)  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;var&lt;/span&gt; cookie = request.Cookies[&lt;span style=&quot;color: #a31515&quot;&gt;&quot;ReturnAfterAuthentication&quot;&lt;/span&gt;];  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;if&lt;/span&gt; (cookie == &lt;span style=&quot;color: #0000ff&quot;&gt;null&lt;/span&gt; || cookie.Expires &amp;gt; &lt;span style=&quot;color: #2b91af&quot;&gt;DateTime&lt;/span&gt;.Now) &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #2b91af&quot;&gt;String&lt;/span&gt;.Empty;  &lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt; cookie.Value;  &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;li&gt;} &lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;I added a full sample that uses the asp.net mvc 3 template to the following github repository: &lt;a href=&quot;https://github.com/eglasius/Cookie-Based-ReturnUrl-After-Authentication-Sample&quot;&gt;https://github.com/eglasius/Cookie-Based-ReturnUrl-After-Authentication-Sample&lt;/a&gt;. You can download a zip file of it directly at: &lt;a title=&quot;https://github.com/eglasius/Cookie-Based-ReturnUrl-After-Authentication-Sample/zipball/master&quot; href=&quot;https://github.com/eglasius/Cookie-Based-ReturnUrl-After-Authentication-Sample/zipball/master&quot;&gt;https://github.com/eglasius/Cookie-Based-ReturnUrl-After-Authentication-Sample/zipball/master&lt;/a&gt;.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/5703348761325234838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2011/09/using-cookies-to-control-return-page.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/5703348761325234838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/5703348761325234838'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2011/09/using-cookies-to-control-return-page.html' title='Using cookies to control return page after login on asp.net mvc 3'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-7860234903453987286</id><published>2010-10-18T23:00:00.000-07:00</published><updated>2010-10-18T23:00:05.574-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="blog"/><category scheme="http://www.blogger.com/atom/ns#" term="blogger"/><category scheme="http://www.blogger.com/atom/ns#" term="digg"/><category scheme="http://www.blogger.com/atom/ns#" term="dotnetkicks"/><category scheme="http://www.blogger.com/atom/ns#" term="dotnetshoutout"/><category scheme="http://www.blogger.com/atom/ns#" term="dzone"/><category scheme="http://www.blogger.com/atom/ns#" term="google buzz"/><category scheme="http://www.blogger.com/atom/ns#" term="hacker news"/><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="reddit"/><category scheme="http://www.blogger.com/atom/ns#" term="yahoo buzz"/><title type='text'>Adding sharing buttons for all your blogger posts</title><content type='html'>&lt;p&gt;The layout I’ll show in this blog post includes sites that are related to software development, but this can be easily be modified by removing them or replacing them with other services appropriate to the specific particular blog.&lt;/p&gt; &lt;p&gt;Open your blogger dashboard and select the &lt;em&gt;design&lt;/em&gt; option for your blog. Use the &lt;em&gt;Download Full Template&lt;/em&gt; option in Edit HTML to save a copy of your current template. This is important to make sure you can go back to your current template if anything goes wrong.&lt;/p&gt; &lt;p&gt;In the Edit Template section select Expand Widget Templates. Search for post-footer-line in the textbox that contains your template. These corresponds to the lines with the built-in blogger sharing options and labels. I used post-footer-line-3 (was empty) and added another one (post-footer-line-4). &lt;/p&gt; &lt;p&gt;Following the html to share on DZone, DotNetShoutout, DotNetKicks, Hacker News, Digg, Reddit, Google Buzz and Yahoo Buzz: &lt;/p&gt; &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:8379bd0b-6c3d-4992-9d39-6f8dbfd94cea&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: html;&quot;&gt;&amp;lt;div class=&#39;post-footer-line post-footer-line-3&#39;&amp;gt;&lt;br /&gt;	&amp;lt;b:if cond=&#39;data:blog.pageType == &amp;amp;quot;item&amp;amp;quot;&#39;&amp;gt;&lt;br /&gt;	 &amp;lt;span style=&#39;top: 5px; position:relative; &#39;&amp;gt;&lt;br /&gt;		 &amp;lt;script type=&#39;text/javascript&#39;&amp;gt; &lt;br /&gt;			var dzone_url = &#39;&amp;lt;data:post.url/&amp;gt;&#39;;&lt;br /&gt;			var dzone_title = &#39;&amp;lt;data:post.title/&amp;gt;&#39;; &lt;br /&gt;			var dzone_style = &#39;2&#39;; &lt;br /&gt;		 &amp;lt;/script&amp;gt;&lt;br /&gt;		 &amp;lt;script language=&#39;javascript&#39; src=&#39;http://widgets.dzone.com/links/widgets/zoneit.js&#39;/&amp;gt;&lt;br /&gt;	 &amp;lt;/span&amp;gt;&lt;br /&gt;	 &amp;lt;a expr:href=&#39;&amp;amp;quot;http://dotnetshoutout.com/Submit?url=&amp;amp;quot; + data:post.url + &amp;amp;quot;&amp;amp;amp;title=&amp;amp;quot; + data:post.title&#39; expr:id=&#39;data:widget.instanceId + &amp;amp;quot;_shoutit&amp;amp;quot;&#39; rel=&#39;nofollow&#39; rev=&#39;vote-for&#39;&amp;gt; &amp;lt;img alt=&#39;Shout it&#39; expr:src=&#39;&amp;amp;quot;http://dotnetshoutout.com/image.axd?url=&amp;amp;quot; + data:post.url&#39; style=&#39;border:0px; top: 2px; position:relative;&#39;/&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;	 &amp;lt;a expr:href=&#39;&amp;amp;quot;http://www.dotnetkicks.com/submit/?url=&amp;amp;quot; + data:post.url + &amp;amp;quot;&amp;amp;amp;title=&amp;amp;quot; + data:post.title&#39; expr:id=&#39;data:widget.instanceId + &amp;amp;quot;_kickit&amp;amp;quot;&#39; rel=&#39;nofollow&#39;&amp;gt;&amp;lt;img alt=&#39;Submit this story to DotNetKicks&#39; expr:src=&#39;&amp;amp;quot;http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=&amp;amp;quot; + data:post.url&#39;/&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;		&amp;lt;a expr:href=&#39;&amp;amp;quot;http://news.ycombinator.com/submitlink?u=&amp;amp;quot; + data:post.url + &amp;amp;quot;&amp;amp;amp;t=&amp;amp;quot; + data:post.title&#39; rel=&#39;nofollow&#39;&amp;gt;&amp;lt;img src=&#39;http://ycombinator.com/images/y18.gif&#39; title=&#39;Submit to Hacker News&#39;/&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;	&amp;lt;/b:if&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div class=&#39;post-footer-line post-footer-line-4&#39;&amp;gt;&lt;br /&gt;	&amp;lt;b:if cond=&#39;data:blog.pageType == &amp;amp;quot;item&amp;amp;quot;&#39;&amp;gt;&lt;br /&gt;		&amp;lt;script type=&#39;text/javascript&#39;&amp;gt;&lt;br /&gt;			(function() {&lt;br /&gt;			var s = document.createElement(&#39;SCRIPT&#39;), s1 = document.getElementsByTagName(&#39;SCRIPT&#39;)[0];&lt;br /&gt;			s.type = &#39;text/javascript&#39;;&lt;br /&gt;			s.async = true;&lt;br /&gt;			s.src = &#39;http://widgets.digg.com/buttons.js&#39;;&lt;br /&gt;			s1.parentNode.insertBefore(s, s1);&lt;br /&gt;			})();&lt;br /&gt;		&amp;lt;/script&amp;gt;&lt;br /&gt;		&amp;lt;span style=&#39;top: 7px; position:relative; margin-right: 5px;&#39;&amp;gt;&lt;br /&gt;			&amp;lt;a class=&#39;DiggThisButton DiggCompact&#39;/&amp;gt;&lt;br /&gt;		&amp;lt;/span&amp;gt;&lt;br /&gt;		&amp;lt;script&amp;gt;&lt;br /&gt;			reddit_url=&#39;&amp;lt;data:post.url/&amp;gt;&#39;;&lt;br /&gt;			reddit_title=&#39;&amp;lt;data:post.title/&amp;gt;&#39;;&lt;br /&gt;		&amp;lt;/script&amp;gt;&lt;br /&gt;		&amp;lt;span style=&#39;top: 10px; position:relative; margin-right: 5px;&#39;&amp;gt;&lt;br /&gt;			&amp;lt;script language=&#39;javascript&#39; src=&#39;http://reddit.com/button.js?t=1&#39;/&amp;gt;&lt;br /&gt;		&amp;lt;/span&amp;gt;&lt;br /&gt;		&amp;lt;a class=&#39;google-buzz-button&#39; data-button-style=&#39;small-count&#39; href=&#39;http://www.google.com/buzz/post&#39; rel=&#39;nofollow&#39; title=&#39;Post to Google Buzz&#39;/&amp;gt;&lt;br /&gt;		&amp;lt;script src=&#39;http://www.google.com/buzz/api/button.js&#39; type=&#39;text/javascript&#39;/&amp;gt;&lt;br /&gt;		&amp;lt;script type=&#39;text/javascript&#39;&amp;gt;&lt;br /&gt;			yahooBuzzArticleHeadline = &#39;&amp;lt;data:post.title/&amp;gt;&#39;;&lt;br /&gt;			yahooBuzzArticleSummary = &#39;&amp;lt;data:post.title/&amp;gt;&#39;;&lt;br /&gt;			yahooBuzzArticleCategory = &#39;science&#39;;&lt;br /&gt;			yahooBuzzArticleType = &#39;text&#39;;&lt;br /&gt;			yahooBuzzArticleId = &amp;lt;data:post.url/&amp;gt;;&lt;br /&gt;		&amp;lt;/script&amp;gt;&lt;br /&gt;		&amp;lt;span style=&#39;display: inline-block;&#39;&amp;gt;&lt;br /&gt;			&amp;lt;script badgetype=&#39;text-votes&#39; src=&#39;http://d.yimg.com/ds/badge2.js&#39; type=&#39;text/javascript&#39;/&amp;gt;&lt;br /&gt;		&amp;lt;/span&amp;gt;&lt;br /&gt;	&amp;lt;/b:if&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Special blogger if at lines 2 and 17 make sure we only display the various share options on the actual post pages. Some of the share code above uses the current page’s URL, so if we wanted to share options in the list of blog posts in the home page of the blog we would need to use alternate sharing code and move the general script files to the blog template.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Spans with relative positioning at lines 3, 27, 34 were added to align the corresponding share buttons.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The span at line 46 makes sure the Yahoo Buzz button code is contained in a block element. This fixes an issue on IE, where the image shows way above the rest of the text.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The line 42 sets the Yahoo Buzz category to science, you might want to use a different category.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://www.dzone.com/links/buttons.jsp&quot;&gt;&lt;font color=&quot;#000000&quot;&gt;Below &lt;/font&gt;&lt;/a&gt;some blog posts used as referenced for some of the share code:&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href=&quot;http://www.ytechie.com/2008/04/dotnetkicks-blogger-integration-that-actually-works.html&quot;&gt;DotNetKicks Blogger integration that actually works!&lt;/a&gt; &lt;br /&gt;&lt;li&gt;&lt;a href=&quot;http://praveenbattula.blogspot.com/2009/11/add-dotnetshoutout-button-in-all-blog.html&quot;&gt;Add Dotnetshoutout button in all blog posts blogger blogs&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/7860234903453987286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2010/10/adding-sharing-buttons-for-all-your.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/7860234903453987286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/7860234903453987286'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2010/10/adding-sharing-buttons-for-all-your.html' title='Adding sharing buttons for all your blogger posts'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-3249160263369764887</id><published>2010-10-17T23:00:00.001-07:00</published><updated>2010-10-17T23:00:00.221-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="c#"/><title type='text'>Disambiguating a method during a .net library upgrade</title><content type='html'>&lt;p&gt;One scenario I had recently, involved a method that was named in such a way that it wasn’t clear the effect it would have given the context. Of course, it came to attention because it was used expecting a different behavior. The upside is that it was detected during a focused integration test, so it was revealed very early in the involved scenario.&lt;/p&gt; &lt;p&gt;As the library is used in more than one project, this raised the question if the code could have been used in such way in any of the other projects. We decided on changing it so we could tell if this was the case during the build of any project that used the library.&lt;/p&gt; &lt;p&gt;Below code sample outlines the approach we used to update the library so developers involved review the usages to the now clearly named alternatives.&lt;/p&gt; &lt;p&gt; &lt;div id=&quot;codeSnippetWrapper&quot;&gt; &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:a9282ae4-baac-4b68-be75-e21834deafb7&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: html;&quot;&gt;[Obsolete(&quot;Use ActionA or ActionB&quot;, true)]&lt;br /&gt;public static void ActionThatWasntClearIfItDidAorB()&lt;br /&gt;{&lt;br /&gt;    ActionA();&lt;br /&gt;}&lt;br /&gt;public static void ActionA()&lt;br /&gt;{&lt;br /&gt;    // original code&lt;br /&gt;}&lt;br /&gt;public static void ActionB()&lt;br /&gt;{&lt;br /&gt;    // alternative code&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/3249160263369764887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2010/10/disambiguating-method-during-net.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/3249160263369764887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/3249160263369764887'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2010/10/disambiguating-method-during-net.html' title='Disambiguating a method during a .net library upgrade'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-797637949677983510</id><published>2010-10-15T23:00:00.000-07:00</published><updated>2010-10-15T23:55:04.806-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="asp.net mvc"/><category scheme="http://www.blogger.com/atom/ns#" term="captcha"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="jquery"/><category scheme="http://www.blogger.com/atom/ns#" term="recaptcha"/><title type='text'>Adding reCAPTCHA with JavaScript</title><content type='html'>&lt;p&gt;In some dynamic interfaces, you may not want to load reCAPTCHA with the initial page loaded. In others you can’t because it would expire by the time the user uses that piece of the UI.&lt;/p&gt; &lt;p&gt;In the above scenarios you can add reCAPTCHA just when you need it.&lt;/p&gt; &lt;p&gt;First include the recaptcha script: &lt;/p&gt; &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:5ec320cb-1958-49ef-a776-fbe2b0b4102a&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: html;&quot;&gt;&amp;lt;script type=&quot;text/javascript&quot; src=&#39;http://www.google.com/recaptcha/api/js/recaptcha_ajax.js&#39;&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/div&gt;If the page is served over https make sure to use that in the above url. Alternatively do it dynamically, like in asp.net MVC you can do: &lt;br /&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:976facd7-97ad-42a3-b5c9-9854d6887f55&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: html;&quot;&gt;&amp;lt;script type=&quot;text/javascript&quot; src=&#39;&amp;lt;%= Request.Url.Scheme + &lt;br /&gt;&quot;://www.google.com/recaptcha/api/js/recaptcha_ajax.js&quot; %&amp;gt;&#39;&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/div&gt;Add an empty div where you’ll want the reCAPTCHA to appear in the HTML. &lt;br&gt;In the corresponding JavaScript action, do: &lt;br /&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:bd13d703-6cad-4d10-8b81-61b097ab431e&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: javascript;&quot;&gt;Recaptcha.create(theRecaptchaPublicKey, targetDiv);&lt;/pre&gt;&lt;/div&gt;If you are using jQuery, one way is to retrieve it based on a css class like: &lt;br /&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:8832d964-14c5-404d-b85d-35567bcf319d&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: javascript;&quot;&gt;$(&#39;#someContainer .captcha&#39;).each(function () {&lt;br /&gt;    Recaptcha.create(theRecaptchaPublicKey, this);&lt;br /&gt;});&lt;/pre&gt;&lt;/div&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/797637949677983510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2010/10/adding-recaptcha-with-javascript.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/797637949677983510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/797637949677983510'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2010/10/adding-recaptcha-with-javascript.html' title='Adding reCAPTCHA with JavaScript'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-6838976737377009974</id><published>2010-10-14T23:00:00.000-07:00</published><updated>2010-10-15T05:45:32.320-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="asp.net mvc"/><category scheme="http://www.blogger.com/atom/ns#" term="captcha"/><category scheme="http://www.blogger.com/atom/ns#" term="recaptcha"/><title type='text'>Adding reCAPTCHA to asp.net MVC</title><content type='html'>&lt;p&gt;These are just a few steps, as the latest reCAPTCHA library has all the pieces you need for asp.net MVC:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Go to &lt;a href=&quot;http://www.google.com/recaptcha/whyrecaptcha&quot;&gt;Get reCAPTCHA&lt;/a&gt;, which gives you the public and private keys you need to use reCAPTCHA with your site  &lt;li&gt;Download the latest .net library at: &lt;a href=&quot;http://code.google.com/p/recaptcha/downloads/list&quot;&gt;http://code.google.com/p/recaptcha/downloads/list&lt;/a&gt;. Currently: &lt;a href=&quot;http://code.google.com/p/recaptcha/downloads/detail?name=recaptcha-dotnet-1.0.4.0-binary.zip&amp;amp;can=2&amp;amp;q=&quot;&gt;dotnet-1.0.4.0&lt;/a&gt;  &lt;li&gt;Add &amp;lt;%= Html.GenerateCaptcha()%&amp;gt; to the form you want to protect with the reCAPTCHA. Naturally you have to add the namespace for the extension to be recognized, some of the options:  &lt;ul&gt; &lt;li&gt;Add the namespace to the web.config:  &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:a50cdc58-c779-4273-8e6a-fdad2665a58e&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: xml;&quot;&gt;&amp;lt;pages&amp;gt;&lt;br /&gt;      &amp;lt;namespaces&amp;gt;&lt;br /&gt;...&lt;br /&gt;        &amp;lt;add namespace=&quot;Recaptcha&quot; /&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;li&gt;Add the namespace at the view: &lt;br&gt;&lt;br /&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:d5127a93-acb5-4b19-adfc-bf47eccd055a&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: html;&quot;&gt;&amp;lt;%@ Import Namespace=&quot;Recaptcha&quot; %&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;li&gt;Add your own extension method that wraps it. I changed the signature to return MvcHtmlString to prevent double encoding when using it with “&amp;lt;%:” instead of “&amp;lt;%=” &lt;br&gt;&lt;br /&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:a1a4d1c5-0816-4154-953e-f7b0f1374609&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public static MvcHtmlString GenerateCaptcha(this HtmlHelper htmlHelper)&lt;br /&gt;{&lt;br /&gt;    var html = Recaptcha.RecaptchaControlMvc.GenerateCaptcha(htmlHelper);&lt;br /&gt;    return MvcHtmlString.Create(html);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;Add the RecaptchaControlMvc.CaptchaValidator attribute to your controller. Also add parameters named captchaIsValid and captchaErrorMessage. Just like:&lt;br&gt;&lt;br /&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:bd574edd-ae85-46a9-97db-058ce1e62821&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;[RecaptchaControlMvc.CaptchaValidator]&lt;br /&gt;public ActionResult MyMethod(Something else, bool captchaValid, string captchaErrorMessage)&lt;br /&gt;{&lt;br /&gt;// do something if (!captchaValid)&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;li&gt;Configure your keys. Some options: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Add to appsettings in the web.config, with entries named: RecaptchaPublicKey and RecaptchaPrivateKey &lt;br /&gt;&lt;li&gt;Set at Application Start:&lt;br&gt;&lt;br /&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:eba918ce-4d4d-49a4-8385-e6552e1b53bf&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;RecaptchaControlMvc.PrivateKey = privKey;&lt;br /&gt;RecaptchaControlMvc.PublicKey = pubKey;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/6838976737377009974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2010/10/adding-recaptcha-to-aspnet-mvc.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/6838976737377009974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/6838976737377009974'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2010/10/adding-recaptcha-to-aspnet-mvc.html' title='Adding reCAPTCHA to asp.net MVC'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-5892915736975854078</id><published>2010-10-13T23:00:00.001-07:00</published><updated>2010-10-13T23:00:06.632-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="asp.net"/><category scheme="http://www.blogger.com/atom/ns#" term="asp.net mvc"/><category scheme="http://www.blogger.com/atom/ns#" term="padding oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>Protecting asp.net machine keys and connection strings</title><content type='html'>&lt;p&gt;Last month I blogged about &lt;a href=&quot;http://asp.net padding oracle: how it relates to getting the web.config, forging authentication cookies and reading other sensitive data&quot;&gt;how the asp.net padding oracle vulnerability related to getting different levels of access to the application&lt;/a&gt;, where part of it involved gaining access to unprotected machine keys at the web.config of the affected sites.&lt;/p&gt; &lt;p&gt;While the Microsoft’s patch that closes the vulnerability is already on Windows Update and other distribution channels, it doesn’t mean we shouldn’t pay attention to keeping important access information of our application out of harms way.&lt;/p&gt; &lt;h3&gt;Protecting config sections&lt;/h3&gt; &lt;p&gt;One way to protect machine keys, connection strings and other sensitive information in the web.config is to use protected sections. Check Microsoft’s &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dtkwfdky.aspx&quot;&gt;Walkthrough: Encrypting Configuration Information Using Protected Configuration&lt;/a&gt;, for steps to use them in your application. By using this approach, the information is no longer in clear text in the web.config, and is encrypted with a key that’s not anywhere in the web site’s folder.&lt;/p&gt; &lt;h3&gt;Machine’s level web.config&lt;/h3&gt; &lt;p&gt;If the server isn’t shared with third party applications, another option is to configure the machine key at the machine level’s web.config. This is another way the machine key wouldn’t have been exposed in the event access to the site’s folder was gained, like in the recent vulnerability. &lt;/p&gt; &lt;p&gt;For .net 4, look it at: %systemroot%\Microsoft.NET\Framework\v4.0.30319\Config\. Note that for .net 3 and 3.5, it uses the same config than the 2.0 framework.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/5892915736975854078/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2010/10/protecting-aspnet-machine-keys-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/5892915736975854078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/5892915736975854078'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2010/10/protecting-aspnet-machine-keys-and.html' title='Protecting asp.net machine keys and connection strings'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-7397028884382521668</id><published>2010-10-12T22:14:00.001-07:00</published><updated>2010-10-13T22:38:24.504-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="nupack"/><category scheme="http://www.blogger.com/atom/ns#" term="powershell"/><category scheme="http://www.blogger.com/atom/ns#" term="visual studio"/><title type='text'>NuPack Visual Studio Add Package References Crash and TypeLoadException</title><content type='html'>&lt;p&gt;This is about a couple issues I found just after deciding to give NuPack a go, and what to do if you see them.&lt;/p&gt; &lt;h3&gt;Add Package References - unloaded projects&lt;/h3&gt; &lt;p&gt;After installing, I tried the &lt;em&gt;Add Package References&lt;/em&gt; on an existing small solution. There it crashed. This wasn’t the same scenario described at &lt;a href=&quot;http://blog.tatham.oddie.com.au/2010/10/07/yet-another-debugging-tale-visual-studio-disappearing/&quot;&gt;Yet Another Debugging Tale – Visual Studio Disappearing&lt;/a&gt;, since the classic Solution Explorer was used and at least I got the closing notification during the crash.&lt;/p&gt; &lt;p&gt;A quick look at the solution I had opened revealed the likely cause: a couple projects in the solution that could not be loaded. So I quickly confirmed it, removed those projects and tried again, problem gone. Bug reported.&lt;/p&gt; &lt;h3&gt;Package Manager Console reports TypeLoadException&lt;/h3&gt; &lt;p&gt;When opening the console you see the below:&lt;/p&gt; &lt;div style=&quot;border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px&quot; id=&quot;codeSnippetWrapper&quot;&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot; id=&quot;codeSnippet&quot;&gt;System.TypeLoadException: Could not load type &#39;System.Management.Automation.Runspaces.InitialSessionState&#39; from assembly &#39;System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&#39;.&lt;br&gt;   at NuPackConsole.Host.PowerShell.Implementation.PowerShellHostProvider.CreateHost(IConsole console)&lt;br&gt;   at NuPackConsole.Implementation.PowerConsole.HostInfo.get_WpfConsole()&lt;br&gt;   at NuPackConsole.Implementation.PowerConsoleToolWindow.get_WpfConsole()System.InvalidOperationException: Can&#39;t start ConsoleDispatcher. Host is null.&lt;br&gt;   at NuPackConsole.Implementation.Console.ConsoleDispatcher.Start()&lt;br&gt;   at NuPackConsole.Implementation.PowerConsoleToolWindow.MoveFocus(FrameworkElement consolePane)&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;The trace is a big tell here, since it mentions PowerShell right there. Searched and installed Power Shell, and I had an operational console. Specifically I used: &lt;a href=&quot;http://support.microsoft.com/kb/968930&quot;&gt;Windows Management Framework Core package&lt;/a&gt; which contains PowerShell 2.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/7397028884382521668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2010/10/nupack-visual-studio-add-package.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/7397028884382521668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/7397028884382521668'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2010/10/nupack-visual-studio-add-package.html' title='NuPack Visual Studio Add Package References Crash and TypeLoadException'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-2565690187799745890</id><published>2010-10-03T21:46:00.001-07:00</published><updated>2010-10-13T22:12:37.809-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="amazon"/><category scheme="http://www.blogger.com/atom/ns#" term="aws"/><category scheme="http://www.blogger.com/atom/ns#" term="centos"/><category scheme="http://www.blogger.com/atom/ns#" term="ec2"/><category scheme="http://www.blogger.com/atom/ns#" term="linode"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="putty"/><category scheme="http://www.blogger.com/atom/ns#" term="rsync"/><category scheme="http://www.blogger.com/atom/ns#" term="scp"/><category scheme="http://www.blogger.com/atom/ns#" term="ssh"/><title type='text'>Migrating CentOS servers from Linode to Amazon EC2, or what I did at the end</title><content type='html'>&lt;p&gt;The guys at &lt;a href=&quot;http://www.619cloud.com&quot; target=&quot;_blank&quot;&gt;619Cloud&lt;/a&gt; have built an interesting script to &lt;a href=&quot;http://www.619cloud.com/blog/migrate-linux-servers-across-cloud-providers/&quot; target=&quot;_blank&quot;&gt;migrate Linux servers across cloud providers&lt;/a&gt;. Although it was created specifically for CentOS 5.X servers, the mechanisms it uses are simple enough that should work with most Linux distributions.&lt;/p&gt; &lt;p&gt;The script is very simple, as it mainly uses &lt;a href=&quot;http://en.wikipedia.org/wiki/Rsync&quot; target=&quot;_blank&quot;&gt;rsync&lt;/a&gt; to efficiently copy everything (excluding some special folders) over SSH to the target server. Because of this, the kernel version of the target server must be the same, as otherwise you could have unexpected issues.&lt;/p&gt; &lt;p&gt;Some bits related to the journey: &lt;/p&gt; &lt;ul&gt; &lt;li&gt;You can use rsync with the .pem key files you get when setting the new EC2 box. In fact you can use the following rsync option to set any other SSH parameters: --rsh &quot;ssh –i pathToPemFile&quot;.  &lt;li&gt;Make sure you do chmod 400 to the key file, otherwise SSH will reject using it.  &lt;li&gt;You can use scp if you just need to copy a couple small files. From a Windows box you can use &lt;a href=&quot;http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html&quot; target=&quot;_blank&quot;&gt;pscp&lt;/a&gt; from Putty.  &lt;li&gt;If you do use the script / rsync to copy from root, make sure you don’t have any network locations mounted in the file system. Ignore this and you’ll get a lot more than you asked for. Alternatively you can explicitly exclude them, like the script does for some system dirs.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I tried using the script on a migration from Linode to Amazon Elastic Compute Cloud (EC2) and ran into issues where the newly created target boxes would lock down. It could have been because of not using the same kernel version (there wasn’t a matching ami), because of Amazon’s kernel modifications or maybe something as simple as network/firewall related configurations on the box that prevented it to work on the new environment.&lt;/p&gt; &lt;p&gt;After being faced with the above, I decided it was time to avoid the issue altogether and try a different approach. This is what I did at the end after I had an EC2 box (with ebs) that I was having trouble getting up, but already had all the data I needed (from the use of the script):&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Stopped the EC2 instance  &lt;li&gt;Detached the ebs volume  &lt;li&gt;Launched a new EC2 instance  &lt;li&gt;Attached the ebs volume  &lt;li&gt;Moved the data out of the ebs volume, as I didn’t want all the rest of the system or application files it contained  &lt;li&gt;Quickly installed the services we had in the original box and pointed them to/imported the original data&lt;/li&gt;&lt;/ul&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/2565690187799745890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2010/10/migrating-centos-servers-from-linode-to.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/2565690187799745890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/2565690187799745890'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2010/10/migrating-centos-servers-from-linode-to.html' title='Migrating CentOS servers from Linode to Amazon EC2, or what I did at the end'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-136275061111221771</id><published>2010-09-30T02:12:00.000-07:00</published><updated>2010-10-13T22:11:40.103-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="form"/><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="jquery"/><title type='text'>Preventing double submit on multi button forms with jquery</title><content type='html'>Note that this is just a fast feedback mechanism, it shouldn&#39;t replace server side logic to prevent double submits. This is specially true if the operations can’t be easily reverted or there would be associated costs to reversing the operation.&lt;br&gt;&lt;br&gt;With that out of the way, lets get right to the code:&lt;br&gt;&lt;br&gt; &lt;div id=&quot;codeSnippetWrapper&quot;&gt; &lt;div style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot; id=&quot;codeSnippet&quot;&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum1&quot;&gt;   1:&lt;/span&gt; $(document).ready(&lt;span style=&quot;color: blue&quot;&gt;function&lt;/span&gt; () {&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum2&quot;&gt;   2:&lt;/span&gt;     $(&lt;span style=&quot;color: #006080&quot;&gt;&#39;form&#39;&lt;/span&gt;).submit(&lt;span style=&quot;color: blue&quot;&gt;function&lt;/span&gt; (e) {&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum3&quot;&gt;   3:&lt;/span&gt;         &lt;span style=&quot;color: blue&quot;&gt;var&lt;/span&gt; theForm = $(&lt;span style=&quot;color: blue&quot;&gt;this&lt;/span&gt;);&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum4&quot;&gt;   4:&lt;/span&gt;         &lt;span style=&quot;color: blue&quot;&gt;var&lt;/span&gt; isValid = doSomeFormValidations(theForm);&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum5&quot;&gt;   5:&lt;/span&gt;         &lt;span style=&quot;color: blue&quot;&gt;if&lt;/span&gt; (!isValid) &lt;span style=&quot;color: blue&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: blue&quot;&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum6&quot;&gt;   6:&lt;/span&gt;         setTimeout(&lt;span style=&quot;color: blue&quot;&gt;function&lt;/span&gt; () {&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum7&quot;&gt;   7:&lt;/span&gt;             &lt;span style=&quot;color: blue&quot;&gt;var&lt;/span&gt; btn = theForm.find(&lt;span style=&quot;color: #006080&quot;&gt;&#39;input[type=&quot;submit&quot;]&#39;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum8&quot;&gt;   8:&lt;/span&gt;             btn.attr(&lt;span style=&quot;color: #006080&quot;&gt;&#39;disabled&#39;&lt;/span&gt;, &lt;span style=&quot;color: #006080&quot;&gt;&#39;disabled&#39;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum9&quot;&gt;   9:&lt;/span&gt;             btn.val(&lt;span style=&quot;color: #006080&quot;&gt;&#39;Processing&#39;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum10&quot;&gt;  10:&lt;/span&gt;          }, 10);&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum11&quot;&gt;  11:&lt;/span&gt;         &lt;span style=&quot;color: blue&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: blue&quot;&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum12&quot;&gt;  12:&lt;/span&gt;     });&lt;/pre&gt;&lt;pre style=&quot;border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px&quot;&gt;&lt;span style=&quot;color: #606060&quot; id=&quot;lnum13&quot;&gt;  13:&lt;/span&gt; });&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;Replace doSomeFormValidations with your own logic and you are good to go. There are other alternatives you might already be using, like having the button disabled until all validations passes. The important bit there is to make sure it’ll only disable the buttons if all validations passed.&lt;br&gt;&lt;br&gt;Now lets go over some pieces and why those are relevant to it working with multi button forms. &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;return &lt;code&gt;true&lt;/code&gt;/&lt;code&gt;false&lt;/code&gt; in the submit body: &lt;code&gt;true&lt;/code&gt; moves forward with the submit, while &lt;code&gt;false&lt;/code&gt; cancels it.&amp;nbsp; &lt;ul&gt;&lt;br /&gt;&lt;li&gt;An alternative to this is returning &lt;code&gt;false&lt;/code&gt;, unbinding our submit function and explicitly calling &lt;code&gt;theForm.submit()&lt;/code&gt;. While this seems to work in the multiple button scenario, we are playing with fire here. We are relying on jquery or the underlying browser events/functions to send that last clicked button’s value. This is an implicit assumption we would be making, and it&#39;s usually based on works on my machine.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;Disabling the submit buttons &amp;amp; adding a processing message for the user:&amp;nbsp; &lt;ul&gt;&lt;br /&gt;&lt;li&gt;No delay: has the undesired side effect that the button’s value isn&#39;t sent with the request in some browsers. Additionally it can even prevent the submit if it were disabled on the button’s click instead of the form’s submit. This is not totally unexpected as we are &lt;em&gt;disabling the button&lt;/em&gt;. In fact, disabling any other input element (textboxes, select, etc.) can cause that data not to be sent to the server just like with our selected button’s value.&amp;nbsp; &lt;li&gt;Delay: By adding an insignificant delay, we let the rest of the submit behavior do its thing, so all the values in the form are sent in the request, including the selected button’s value. After those values are grabbed by the submit, we can disable controls and change values without affecting what will be sent to the server.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;Don’t call use an id/name of ‘&lt;code&gt;submit&lt;/code&gt;’ in your buttons. While not shown in the above code, this is important as it could cause conflicts with the submit events.&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;I want to stress out what I just mentioned in the no delay bullet. Just disabling any input of the form right away, will prevent the value from being sent to the server in some browsers. &lt;br&gt;&lt;br&gt;This can easily get you into a situation where you can&#39;t figure out why the button pressed isn&#39;t being sent to the server, specially if you are working on an already built third party site. So if you are missing any input, first use a developer tool to inspect the elements and then go through the scripts, it&#39;s very likely somewhere in there.&lt;br&gt;&lt;br&gt;You can tweak the above function to fit your needs, like display a different message, hide part of the UI, take actions if it&#39;ll timeout.  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/136275061111221771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2010/09/preventing-double-submit-on-multi_30.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/136275061111221771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/136275061111221771'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2010/09/preventing-double-submit-on-multi_30.html' title='Preventing double submit on multi button forms with jquery'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-4900800106523422789</id><published>2010-09-24T14:43:00.001-07:00</published><updated>2010-10-13T22:38:01.892-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="asp.net"/><category scheme="http://www.blogger.com/atom/ns#" term="asp.net mvc"/><category scheme="http://www.blogger.com/atom/ns#" term="hmac"/><category scheme="http://www.blogger.com/atom/ns#" term="padding oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>asp.net padding oracle: impact on asp.net MVC and PHP</title><content type='html'>&lt;p&gt;2 days ago, I wrote about how the padding oracle vulnerability related to &lt;a href=&quot;http://eglasius.blogspot.com/2010/09/aspnet-padding-oracle-how-it-relates-to.html&quot; target=&quot;_blank&quot;&gt;getting various levels of access in ASP.NET&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;Let’s see how all the items I mentioned on my earlier post relate to ASP.NET MVC (and some news):&lt;/p&gt; &lt;ul&gt; &lt;li&gt;View State: We don’t use it  &lt;li&gt;Session cookies: Unrelated to the attack  &lt;li&gt;Authentication cookies: These are signed, so you have to actually get the keys to be able to get around it. Additionally, by using the Microsoft workaround, we make sure we don’t expose information on the decryption with it  &lt;li&gt;Custom encryption using the machine key. This is susceptible, make sure that if you are receiving anything unexpected out of the Decrypt call you throw an error / just like if it the Decrypt call had failed. That along with the Microsoft workaround will prevent decryption information being exposed. See &lt;a href=&quot;http://stackoverflow.com/questions/3720720/how-serious-is-this-new-asp-net-security-vulnerability-and-how-can-i-workaround-i/3721473#3721473&quot;&gt;Understanding Padding Oracle Attacks&lt;/a&gt; for more information on why that matters. For best results, consider if you can avoid sending it to the client altogether, or sign/validate the data  &lt;li&gt;&lt;em&gt;WebResource.axd&lt;/em&gt; and &lt;em&gt;ScriptResource.axd&lt;/em&gt;: These built-in are a huge problem in this vulnerability, but as we don’t use them, we disable them (see the side note below)  &lt;li&gt;&lt;code&gt;HtmlHelper.AntiForgeryToken&lt;/code&gt;: uses the machinekey to encrypt the cookie but uses it with mac to make sure it hasn’t been modified. Not a problem if you use the Microsoft workaround / don’t disclose details on the error.  &lt;li&gt;I might be missing some, so pay attention to any other feature that uses encryption/decryption.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Additionally, use security best practices all around, don’t send sensitive data to the client, don’t assume anything you sent to the browser hasn’t been tampered, keep your connection strings safe, have a firewall that further prevents external access, act as if the &lt;em&gt;web.config&lt;/em&gt; could be read from outside (protected sections or any other measure).&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Beyond the ASP.NET features:&lt;/strong&gt; You don’t need to be using anything at all of the ASP.NET platform, to be vulnerable in an IIS install that has ASP.NET enabled. If the framework is 3.5 SP1 or above, this means access to any special file in the site’s folder (including your aspx/php files, config files, embedded data files). Here is a blog post more specific to PHP in IIS: &lt;a href=&quot;http://ruslany.net/2010/09/asp-net-vulnerability-affecting-php-sites-on-iis/&quot;&gt;ASP.NET vulnerability affecting PHP sites on IIS&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;ASP.NET MVC is impacted by the above as well. The access to any file issue, is caused by the built-in handlers I mentioned above: &lt;em&gt;WebResource.axd&lt;/em&gt; and &lt;em&gt;ScriptResource.axd&lt;/em&gt;. Exactly which handler config you need to disable depends on the IIS version / mode (classic vs. integrated) and the version, I don’t have a compiled list, but you can find the list of handlers added in the machine &lt;em&gt;web.config&lt;/em&gt; (.NET Framework in the Windows folder) for the classic mode or the IIS &lt;em&gt;applicationHost.config&lt;/em&gt; for integrated mode. It’s a good exercise to take a look at those anyway.&lt;/p&gt; &lt;p&gt;Removing the handlers means the attacker can no longer get to the special files (including &lt;em&gt;web.config&lt;/em&gt;) in your site. That said, you still want to prevent the attacker from gaining ground into your site’s encryption/decryption protections related to the machine key. So, regardless of what we discussed above, go and apply the Microsoft workaround.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/4900800106523422789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2010/09/aspnet-padding-oracle-impact-on-aspnet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/4900800106523422789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/4900800106523422789'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2010/09/aspnet-padding-oracle-impact-on-aspnet.html' title='asp.net padding oracle: impact on asp.net MVC and PHP'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4134530225370527924.post-6108892465287728434</id><published>2010-09-22T15:05:00.001-07:00</published><updated>2010-10-13T22:37:35.760-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".net"/><category scheme="http://www.blogger.com/atom/ns#" term="asp.net"/><category scheme="http://www.blogger.com/atom/ns#" term="asp.net mvc"/><category scheme="http://www.blogger.com/atom/ns#" term="hmac"/><category scheme="http://www.blogger.com/atom/ns#" term="padding oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><category scheme="http://www.blogger.com/atom/ns#" term="sharepoint"/><title type='text'>asp.net padding oracle: how it relates to getting the web.config, forging authentication cookies and reading other sensitive data</title><content type='html'>&lt;p&gt;This ASP.NET security vulnerability is certainly very serious: &lt;a href=&quot;http://www.microsoft.com/technet/security/advisory/2416728.mspx&quot; target=&quot;_blank&quot;&gt;(2416728) Vulnerability in ASP.NET Could Allow Information Disclosure&lt;/a&gt;. Scott Guthrie from Microsoft has a &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2010/09/18/important-asp-net-security-vulnerability.aspx&quot; target=&quot;_blank&quot;&gt;couple good blog posts&lt;/a&gt; about it. Those links contain information about the current workaround. &lt;strong&gt;Important Update: &lt;/strong&gt;Microsoft published the patch, make sure to use that instead of the workaround – Scott blogged the details &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2010/09/30/asp-net-security-fix-now-on-windows-update.aspx&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;When successful, the attacker can decrypt any value sent to the client encrypted with the ASP.NET key. Examples of these are authentication cookies and encrypted View State (this last one is not necessarily encrypted to begin with depending on the configuration).&lt;/p&gt; &lt;p&gt;Having the ability to decrypt any value, also gives the attacker the ability to re-encrypt a modified version of the data. It’s not without restrictions, as the mechanism that allows to do so requires a piece of garbage data the attacker can’t control to end somewhere in the message. The attacker controls where in the message the garbage appears, depending on the message the garbage can be put in a location that is irrelevant or have a side effect the attacker doesn’t care about. The size of the garbage matches the block size, so we are talking 16 bytes for a 128 bit encryption.&lt;/p&gt; &lt;p&gt;It’s important to note that at this stage the attacker doesn’t hold the actual keys. This is important, as it means the attacker can’t get through signed values. Even if the ability to re-encrypt were related to the signing of the values, the attacker will still end with garbage somewhere in the message, making it very hard to produce a valid signature.&lt;/p&gt; &lt;p&gt;So far the attacker gets any sensitive information stored in all those encrypted values sent to the client. So let’s take a look at some scenarios:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Ability to view all view state data.  &lt;ul&gt; &lt;li&gt;By default the data isn’t really encrypted, so it’s usually not new you can get to that data.  &lt;li&gt;When following best practices there isn’t anything in there that matters, and also the app shouldn’t rely on it being tamper proof.  &lt;li&gt;Above said, if it’s configured to validate the View State using HMAC, it prevents the attacker at this stage from posting modified View State.  &lt;li&gt;While there may not be sensitive information in the View State, it could still be the padding oracle the attacker needs.&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Ability to read session cookies.  &lt;ul&gt; &lt;li&gt;This is totally unrelated to the attack since these cookies contain an encoded value generated by a random cryptographic provider (so it can’t be predicted). In other words, these cookies aren’t encrypted at all.  &lt;li&gt;For extra protection, you can store a value you can relate to the authentication in the session and check authentication vs. session to make sure the user owns that session. Of course that won’t work if the feature works for anonymous users, although you could emit a special ticket for those users if it’s important to protect the session.&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Ability to read the authentication cookie.  &lt;ul&gt; &lt;li&gt;This just allows the user to see the username, and how the rest of the structure of the ticket is created.  &lt;li&gt;As the authentication ticket in the cookie is signed, the attacker can’t forge other user’s cookie with the padding oracle attack so far.  &lt;li&gt;If the attacker sniffed an authentication cookie/ticket, then the account was already compromised, regardless of this attack.  &lt;li&gt;As the authentication cookies are always sent in each request, the only way to really protect them would be to have all requests that send the cookie back through https. See the “Cookie hijacking” section in &lt;a href=&quot;http://en.wikipedia.org/wiki/HTTP_cookie&quot;&gt;http://en.wikipedia.org/wiki/HTTP_cookie&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Any custom use of encryption using machine key in the site.  &lt;ul&gt; &lt;li&gt;The data will be able to be decrypted after the successful attack.  &lt;li&gt;It could also be attacked directly if no measures that consider padding oracle exposure are taken. Even with the Microsoft workaround mentioned in the advisory, the code might suffer from the issue / by not dealing with the invalid data as it were a failed decryption.&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;strong&gt;WebResource.axd – here gets uglier:&lt;/strong&gt;  &lt;ul&gt; &lt;li&gt;This feature is used by ASP.NET to allow serving embedded resources. An example of these would be embedded CSS files that belong to a custom control and are embedded for ease of distribution.  &lt;li&gt;This special handler only uses decryption to receive which embedded resource it will use. This means the attacker can forge valid requests / putting some garbage in an irrelevant part of the message.  &lt;li&gt;&lt;strong&gt;The request includes which assembly the resource is in, so the attacker has gained the ability to access any embedded resource in any assembly accessible to the application&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;strong&gt;ScriptResource.axd – the real deal:&lt;/strong&gt;  &lt;ul&gt; &lt;li&gt;This feature is related to serving combined script files into one (js), which might belong to multiple controls, but it’s not restricted to it. That’s what it’s supposed to be for, but I can’t confirm if it has other intended users.  &lt;li&gt;It works just like &lt;em&gt;WebResource.axd&lt;/em&gt;, only encryption / no signing.  &lt;li&gt;Its scope is beyond just serving embedded resources, it also serves files.  &lt;li&gt;The files served aren’t restricted to be JavaScript files, so it can serve any file.  &lt;li&gt;&lt;strong&gt;The above means the attacker has gained the ability to access any file accessible to the application. It’s not restricted to only js files, and doesn’t take any special action to block special files. One of such files is the &lt;em&gt;web.config&lt;/em&gt;&lt;/strong&gt;.  &lt;li&gt;ASP.NET normally uses the handlers configuration to determine which files are not accessible, so &lt;em&gt;web.config&lt;/em&gt; is configured with an access forbidden handler. This specific mechanism isn’t used by &lt;em&gt;ScriptResource.axd&lt;/em&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The workaround to prevent the attack from reaching this stage is at the beginning. &lt;/p&gt; &lt;p&gt;It’s obvious that gaining access to the &lt;em&gt;web.config&lt;/em&gt; is very serious in ASP.NET (not dismissing all the rest of the accesses so far). The file is considered by many as something specially protected by ASP.NET that shouldn’t ever be exposed from the ASP.NET application. Sure it’s a wrong assumption, but it’s a common one. Not assuming is secured means extra complexity, like using encrypted values and having the key elsewhere in the server / with the corresponding configurations, permissions and then dealing with deploying that in web farms scenarios.&lt;/p&gt; &lt;p&gt;While special access info might be exposed in the &lt;em&gt;web.config&lt;/em&gt;, there could be other measures in place that prevent doing something with it. Things like the database not being accessible from outside, other pieces being behind a firewall, extra measures to get in, etc. All that said, it eases the attacker’s job a lot on preparing an attack at those levels.&lt;/p&gt; &lt;p&gt;Something that sometimes happens with &lt;em&gt;web.config&lt;/em&gt;, specially on web farms scenario / or hosted scenarios, is that other keys like the machinekey ends up being set in the &lt;em&gt;web.config&lt;/em&gt;. Clearly, the consequences with the current vulnerability in the wild are catastrophic. &lt;strong&gt;Once the attacker gains access to those keys, the ability to sign is gained, which means any request can be forged, signed or not; can now forge an authentication cookie. &lt;/strong&gt;At least with the default forms authentication implementation, there is a question about it here: &lt;a href=&quot;http://stackoverflow.com/questions/3751047/is-there-a-different-way-to-do-asp-net-forms-authentication-thats-already-built/3767382#3767382&quot; target=&quot;_blank&quot;&gt;is-there-a-different-way-to-do-asp-net-forms-authentication-thats-already-built&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;The DotNetNuke was an ASP.NET application that they picked as a demonstration of the size of the issue. The default install generates machinekey at the site level, so by using the oracle padding attack, they get to forge an authentication user of an admin. What is worst is that they combined the new access the admin account gives them with a separate vulnerability/attack and can manage to get up to System privilege on the target server.&lt;/p&gt; &lt;p&gt;If you haven’t after seeing the links at the top, go and apply the workaround to your applications now. If you want to know about what a padding oracle attack is, check out: &lt;a href=&quot;http://stackoverflow.com/questions/3720720/how-serious-is-this-new-asp-net-security-vulnerability-and-how-can-i-workaround-i/3721473#3721473&quot; target=&quot;_blank&quot;&gt;Understanding Padding Oracle Attacks&lt;/a&gt;. If you are in ASP.NET MVC, Sharepoint or anything else that’s hosted in ASP.NET, yes you are vulnerable if you don’t have the workaround in place (or good equivalent).&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eglasius.blogspot.com/feeds/6108892465287728434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://eglasius.blogspot.com/2010/09/aspnet-padding-oracle-how-it-relates-to.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/6108892465287728434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4134530225370527924/posts/default/6108892465287728434'/><link rel='alternate' type='text/html' href='http://eglasius.blogspot.com/2010/09/aspnet-padding-oracle-how-it-relates-to.html' title='asp.net padding oracle: how it relates to getting the web.config, forging authentication cookies and reading other sensitive data'/><author><name>Freddy Rios</name><uri>http://www.blogger.com/profile/15710276929321161395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSqVmB8sbRGFrpmxpt7_jwGZrrp0ErPSwdpwVF9vESfuhE89dWXP1f-v2vJb-AGED2DVoiq2vW8oaaeRi701lpNB3g5T0y7ovHjdXkDS4IiSWmWTrwIf2gRxfsDEQpjA4/s220/vistaIzquierda.jpg'/></author><thr:total>7</thr:total></entry></feed>