Cookieless Forms Authentication and Redirection

Here's one that had me scratching my head for a bit.

As you might know, in asp.net 2.0 you can choose to have cookieless Forms Authentication (http://msdn.microsoft.com/msdnmag/issues/04/06/ASPNET20Security/). Basically, what this means is that your pages Url's will get increased by about 200% :) because asp.net no longer stores the forms authentication information in a cookie, but directly in the Url. Also, you can have cookieless session state, meaning some extra characters get added again in the Url so asp.net can keep track of the sessions.

Leaving other considerations aside (you can find plenty of discussions about whether cookieless forms auth or cookieless session state are evil on the net), here's my concrete scenario:

My app is configured for both cookieless Session State and Forms Authentication. I have a ForgotPassword page that sits outside of Forms Authentication. On this page, if the user answers his secret question correctly, he will be presented with a hyperlink leading him to the main application page (for example). Here's what i did:

hlHomePage.NavigateUrl = Response.ApplyAppPathModifier("~/Default.aspx");
FormsAuthentication.SetAuthCookie(userName, false);

First i use HttpResponse's ApplyAppPathModifier method to convert my relative Url into one with the session identifier embedded (An url when cookieless sessions are used looks like http://server/vdir/**(S(f4qcbhb21ohizgjh3oz1ej55))**/Pages/...). Then I tell FormsAuthentication that the user is authenticated ok, by calling its SetAuthCookie method. The name of the SetAuthCookie method is actually misleading, because, as I said earlier, i'm using Forms Authentication in cookieless mode. It uses an internal CookielessHelperClass that works with both cookies and cookieless modes (you can check out the actual implementation with Reflector).

The result of the above code was that upon clicking the hyperlink the user would not get redirected to the main application page, but rather to the Forms Authentication Login page. Hmm... Not quite what I had hoped :). Looking at the rendered hyperlink url more closely I noticed that it only seemed to include the session identifier and not also the Forms Authentication id that i would get if i logged in the application successfully (something along the lines of http://server/vdir/((S(f4qcbhb21ohizgjh3oz1ej55)**F(Kzy3JUAcCmwusdlafH3ErXw9v1mGildNkxaxSkcujvPqDOtKg1Z6gvPLVgkSuNzLNjoFWk4EL-t5fjj6hgYrPs7tpjYH19Z3Qnw7Cjfgt741))**/Default.aspx). So maybe ApplyAppPathModifier didn't do something it was supposed to...or did it? Reflector-ing through it I didn't see anything related to FormsAuthentication, so I was back to square one. Then poking through the code i found that doing the following worked:

hlHomePage.NavigateUrl = Response.ApplyAppPathModifier("/Default.aspx");
FormsAuthentication.SetAuthCookie(userName, false);
**Response.Redirect(Response.ApplyAppPathModifier("
/Default.aspx"));**

Thinking to myself how odd that was, it struck me. Maybe I should be setting the hyperlink's NavigateUrl after calling SetAuthCookie:

FormsAuthentication.SetAuthCookie(userName, false);
hlHomePage.NavigateUrl = Response.ApplyAppPathModifier("~/Default.aspx");

...sure enough it worked. But wait, i had previously looked through the ApplyAppPathModifier method and didn't see it "taking" the Forms Authentication id from anywhere and embedding it into the Url it was returning. So I looked again and the following caught my eye:

if ((this**._appPathModifier** != null) && (virtualPath.IndexOf(this**._appPathModifier**, 4) <>
{
      ... do some stuff...
    virtualPath = virtualPath.Substring(0, text1.Length) + this._appPathModifier + "/" + ... etc
}

return virtualPath;

So basically, the _appPathModifier gets appended to the Url i'm passing in. But who sets the value of this private variable? Again, Reflector makes it a snap to find out, and here's the complete call tree:

MyCode -> FormsAuthentication.SetAuthCookie
FormsAuthentication.SetAuthCookie -> CookielessHelperClass.SetCookieValue
CookielessHelperClass.SetCookieValue -> HttpResponse.SetAppPathModifier

What this shows us is that the HttpResponse's ApplyAppPathModifier method does not itself get the Forms Authentication id from anywhere or check how Forms Authentication is configured, but another internal method is exposed (SetAppPathModifier) so someone else (CookielessHelperClass) can set it from the outside. Pretty clear now and also a nice example of Inversion of Control.

To sum up: when using Forms Authentication in cookieless mode and custom redirecting from pages outside of Forms Authentication, remember to cal SetAuthCookie before doing anything else, because otherwise the Url's returned by HttpResponse's ApplyAppPathModifier will not contain the Forms Authentication id, meaning that as far as cookieless Forms Authentication is concerned, the user is not logged in.

This article is part of the GWB Archives. Original Author: Adrian Hara

New on Geeks with Blogs

  • We Won The One Award I Actually Care About

    Full Scale made the Inc. 5000 for the fifth year straight, the 12th listing across my three companies. Here is why the one award you cannot buy is worth stopping for.

  • Your Customers Build the Features Now

    I let a tool I liked sit dead for a year rather than build the features I wanted. An MCP server meant I never had to, and your customers can do the same to your product.

  • Get the Size of a Directory in Linux the Easy Way

    du -sh for the quick answer, ncdu for the cleanup, df for the disk itself: every command for checking directory size in Linux, plus why du and df never agree.

  • Vim Search and Replace: The Ultimate Guide

    One :%s command replaces every match in a file before a find dialog would even open. The Vim substitute patterns worth the muscle memory: flags, ranges, capture groups, and multi-file edits.