Geeks With Blogs
Adrian Hara Working through the .NET maze

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.

Posted on Tuesday, May 2, 2006 1:16 PM | Back to top


Comments on this post: Cookieless Forms Authentication and Redirection

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Adrian Hara | Powered by: GeeksWithBlogs.net