Scott Hanselman

New FormsAuthentication.SignOut behavior in ASP.NET 2.0

July 12, 2005 Comment on this post [6] Posted in ASP.NET | DasBlog
Sponsored By

Calling FormsAuthentication.SignOut() removes the FormsAuthentication cookies in ASP.NET 1.1. Sometimes folks call it from their Login page, like this:

if (!Page.IsPostBack)
{
    FormsAuthentication.SignOut();
}

This says, "If this is a fresh load of this page, clear out the authentication cookies."

If this seems like a reasonable thing, that's because it is. However, if you run an ASP.NET 1.1 site under ASP.NET 2.0 without recompiling, as a number of dasBlog users do, you may get some odd behavior.

You'll visit the Login.aspx page and redirect to the Login.aspx page forever in a loop...it will make your URL look like this:

/Blog/login.aspx?ReturnUrl=%2fBlog%2flogin.aspx%3fReturnUrl%3d%252fBlog%252flogin.aspx%
253fReturnUrl%253d%25252fBlog%25252flogin.aspx%25253fReturnUrl%25253d%2525252fBlog%
525252flogin.aspx%2525253fReturnUrl%2525253d%252525252fBlog%252525252flogin.aspx%
52525253fReturnUrl%252525253d%25252525252fBlog%25252525252flogin.aspx%25252525253fReturnUrl%
5252525253d%2525252525252fBlog%2525252525252flogin.aspx%2525252525253fReturnUrl%2525252525253d%
52525252525252fBlog%252525252525252flogin.aspx%252525252525253fReturnUrl%252525252525253d%
5252525252525252fBlog%25252525252525252flogin.aspx%25252525252525253fReturnUrl%25252525252525253d%
525252525252525252fBlog%2525252525252525252flogin.aspx%2525252525252525253fReturnUrl%
525252525252525253d%252525252525252525252fBlog%252525252525252525252fLogin.aspx

Why? Because ASP.NET 2.0 add this code inside SignOut():

if (FormsAuthentication.CookieMode != HttpCookieMode.UseCookies)
{
    Response.Redirect(FormsAuthentication.GetLoginPage(null), false);
}

That's pretty interesting. If you call SignOut() it redirects you to the Login page, but only if your CookieMode isn't set to UseCookies. This is because ASP.NET 2.0 added support for cookieless FormsAuthentication. They store the auth information in the URL, and they redirect you because they want to clear the authentication info. Makes sense.

What doesn't make sense is why HttpCookieMode doesn't default to UseCookies. It defaults to Cookieless. Which is lovely under ASP.NET 2.0, but not under 1.1. It stays that way and confuses the system.

So, if you see this kind of infinite redirect with FormsAuthentication while running ASP.NET 1.1 applications under ASP.NET 2.0, you can add cookieless="UseCookies" to your <forms> element in web.config:

<forms cookieless="UseCookies" name=".DASBLOGAUTH" protection="All" timeout="60" path="/"/>

And then I went to sleep.

Now playing: Counting Crows - Angels of the Silences

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Weird Timeouts with custom ASP.NET FormsAuthentication

July 12, 2005 Comment on this post [7] Posted in ASP.NET | Bugs
Sponsored By

Ah, life. For me, in what I tend to do day to day, it always seems to come down to debugging weird stuff. So, here's something weird that happened today (actually it's been happening over the last week in QA).

Someone logs into an ASP.NET application successfully and does some stuff. They wait for 10.5 minutes. That means no clicking, just waiting. Then they click and get the next page successfully. Then the click on the NEXT (the second since they've been waiting) and get kicked out to the login page.

Since our FormsAuthentication stuff not only authorizes the user into ASP.NET but also carries with it tokens into other "session-like" systems, folks dug around in those systems initially looking at Audit data, logs, everything. It just doesn't make sense.

The FormsAuthentication timeout is set to 20 minutes and folks are getting "logged out" at 10.5 minutes. They set the timeout to 600 minutes and folks get kicked at 10.5 minutes. Is the timeout value being ignored?

As with most things, we return to first principles and pull out ieHttpHeaders. Why? Because in the context of a Web Application, clicking and looking at HTML only tells you that you clicked and look at some HTML.

TIP: When using ieHttpHeaders or any sniffers, turn OFF Images in your browser. Chances are they aren't the issue (although they might well be) but initially you'll save yourself some clutter in initial debugging.)

So, here's what we saw (abridged and #commented):

#LOGGING IN
POST /fooapp/Login.aspx HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Host: foo.corillian.net
Content-Length: 104
FI=fooapp&Destination=Accounts%2Ffooapp%2Fsummary.aspx&UserName=BAR

#LOGIN COOL, REDIRECTING and setting NEW AUTH COOKIE
HTTP/1.1 302 Found
Date: Mon, 11 Jul 2005 18:54:31 GMT
Server: Microsoft-IIS/6.0
Location:
http://foo.corillian.net/fooapp/somepath.aspx
Set-Cookie: AuthenticationTicket=32EFESNIPCC65879; path=/
Content-Type: text/html; charset=utf-8
Content-Length: 182

#GOING WHERE YOU SAID, RETURNING NEW AUTH COOKIE
GET /fooapp/somepath.aspx HTTP/1.1
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Host: foo.corillian.net
Cookie: AuthenticationTicket=32EFESNIPCC65879

#GOT TO WHERE I WAS GOING
HTTP/1.1 200 OK
Date: Mon, 11 Jul 2005 18:54:32 GMT
Server: Microsoft-IIS/6.0
Content-Type: text/html; charset=utf-8
Content-Length: 18224

WAIT 10.5 MINUTES HERE

#CLICK AND GO TO A NEW PAGE
GET /fooapp/newpage.aspx HTTP/1.1
Referer:
http://foo.corillian.net/fooapp/somepath.aspx
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Host: foo.corillian.net
Cookie: AuthenticationTicket=32EFESNIPCC65879;

#GOT TO THAT NEW PAGE
HTTP/1.1 200 OK
Date: Mon, 11 Jul 2005 19:05:18 GMT
Server: Microsoft-IIS/6.0
Set-Cookie: AuthenticationTicket=AB4665AB0B7495; path=/; secure
Content-Type: text/html; charset=utf-8
Content-Length: 75510

#CLICK AND GO TO THE SECOND PAGE SINCE WE WAITED
GET /fooapp/secondpage.aspx HTTP/1.1
Referer:
http://foo.corillian.net/fooapp/newpage.aspx
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Host: foo.corillian.net
Connection: Keep-Alive

#NO COOKIES WERE PASSED IN, REDIRECTED TO LOGIN!
HTTP/1.1 302 Found
Date: Mon, 11 Jul 2005 19:05:27 GMT
Server: Microsoft-IIS/6.0
Location:
http://foo.corillian.net/fooapp/login.aspx?ReturnUrl=%2ffooapp%2fnewpage.aspx
Content-Type: text/html; charset=utf-8
Content-Length: 209

Where did it all go wrong? Well, we waited 10.5 minutes the clicked. Notice after we waited, we passed in the AuthenticationTicket we had, "32EFESNIPCC65879." This is the one that we generated ourselves in Login.aspx via:

FormsAuthenticationTicket authTicket = new
    FormsAuthenticationTicket(1,   //version
    userName,                    // user name
    DateTime.Now,                  //creation
    DateTime.Now.AddMinutes(Timeout),  //Expiration
    false};
 
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie authCookie = new HttpCookie(
FormsAuthentication.FormsCookieName,encryptedTicket);   
HttpContext.Current.Response.Cookies.Add(authCookie);

This is a pretty typical thing to do when you're doing FormsAuthentication because you want might more control of the Ticket, or you might want to include user specific data in the cookie, etc.

But, after we waited and passed in the value we had, we got issued a NEW AuthenticationTicket with the value "AB4665AB0B7495" which is OK. Because the age of our original AuthenticationTicket was over 50% of the 20 minute timeout, the FormsAuthenticationModule was kind enough to renew the ticket. How nice of them. And a good thing too. They did it because the <forms> section of our web.config had slidingExpiration="true."

However, then the next GET request includes No AuthenticationTicket at all! Why not? Notice the difference between the first issuance and the second. The second issuing of the cookie included "secure" at its end. Why? Because of this setting in the web.config:

<forms requireSSL="true"
    slidingExpiration="true"
    loginUrl="~/login.aspx"
    name="AuthenticationTicket"
    protection="All"
    timeout="20" />

Ah! The first time the AuthenticationTicket was issued, it was issued by our custom code, and we didn't respect this setting! Later - 10.5 minutes later - when FormsAuthentication saw fit to issue a new cookie, they DID respect this flag.

Why was this a problem? Because in development were weren't running under SSL (https://). Had we been running under SSL this never would have been found. Had we gone live without SLL we would have seen flaky (read: impossible to reproduce) bugs with folks getting timeouts that didn't jive with our timeout settings.

The Fix - respect the RequiresSSL flag in the inital issuing of the AuthenticationTicket and we would have seen the problem in development immediately upon login:

// Create the authentication ticket            
FormsAuthenticationTicket authTicket = new
    FormsAuthenticationTicket(1,   //version
    userName,                    // user name
    DateTime.Now,                  //creation
    DateTime.Now.AddMinutes(Timeout),  //Expiration
    false}
 
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName,encryptedTicket);    
 
//Make sure we mark the cookie as "Secure" if RequireSSL is set in the web.config.
// If we don't, the FIRST issuing of this cookie with not be secure 
// (as we are the ones that did it) while the second issuing (when it's
// beign refreshed) will be secure. That would cause intermitant problems with 
// timeout-like behaviors around "timeout/2" minutes into the user's session.
authCookie.Secure = FormsAuthentication.RequireSSL;
HttpContext.Current.Response.Cookies.Add(authCookie);

And then I went to lunch.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Symantec Client Firewall is Psycho

July 10, 2005 Comment on this post [8] Posted in ASP.NET | DasBlog | Bugs
Sponsored By

Some how I got myself into using the Symantec Client Firewall instead of the Windows XP SP2 Firewall.

Today, while doing some local (localhost) debugging, I noticed that when I requested a file called http://localhost/dasblog/themes/elegante/banner.jpg, I was getting back NOTHING. No banner.

Ok, that's weird. So I fired up ieHttpHeaders and saw this (emphasis mine):

GET /DasBlog/themes/elegante/banner.jpg HTTP/1.1
Accept: */*
Accept-Language: en-us,tr;q=0.5
Accept-Encoding: gzip, deflate
If-Modified-Since: Fri, 25 Aug 2000 01:00:00 GMT; length=881
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Tablet PC 1.7; .NET CLR 2.0.50215)
Host: localhost
Connection: Keep-Alive

HTTP/1.0 200 OK
Server: Netscape-Enterprise/2.0a
Pragma: No-cache
Date: Fri, 25 Aug 2000 23:00:00 GMT
Last-modified: Fri, 25 Aug 2000 01:00:00 GMT
Accept-Ranges: bytes
Content-length: 881
Content-type: image/gif

Holy crap! Do I have a Trojan? Spyware? I don't have Netscape anything running on my system. Notice the weird date, the weird Content-length for what was supposed to be a 35k file. I was getting all ready to look at who's got what open on what port, I ran Spyware scans with Search&Destroy and Microsoft AntiSpyware...then I thought, maybe it was AdBlock within FireFox. No, that doesn't make sense, I'm in IE. Who else could be messing around...

Damn you Norton! I disabled the Symantec Client Firewall and poof, there was my banner.

GET /DasBlog/themes/elegante/banner.jpg HTTP/1.1
Accept: */*
Accept-Language: en-us,tr;q=0.5
Accept-Encoding: gzip, deflate
If-Modified-Since: Fri, 25 Aug 2000 01:00:00 GMT; length=881
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Tablet PC 1.7; .NET CLR 2.0.50215)
Host: localhost
Connection: Keep-Alive

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
X-Powered-By: ASP.NET
Date: Sun, 10 Jul 2005 05:43:40 GMT
Content-Type: image/jpeg
Accept-Ranges: bytes
Last-Modified: Sun, 10 Jul 2005 01:31:50 GMT
ETag: "ae93325ef84c51:8ad"
Content-Length: 36634

Turns out that Symantec Client Firewall has their own brand of ad blocking built in. That's not a bad thing except:

  • They block any graphic requested with the name "banner" anywhere in it - hence the fake HTTP Response.
  • The perform this blocking/sniffing even on requests to your OWN MACHINE (localhost)

Sigh. 7 minutes wasted. Hopefully this tidbit will save you a little time one day.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Toolbars Galore

July 09, 2005 Comment on this post [10] Posted in Gaming | Tools
Sponsored By

I like to keep my [browser] toolbars simple. I've seen toolbars stacked 8 deep and I think that's wasted space. But, every once in a while a toolbar comes along that I can get behind. Here's the toolbars I've installed this week:

  • Google (official) Toolbar BETA for FireFox - This is the official Google one with PageRank, not the GoogleBar from MozDev we've all no doubt be running previously. I've disabled the GoogleBar and installed the new one, and I'm digging it.
  • The Google Suggest FireFox Extension - The toolbar is nice, but it's not for everyone. This is a little gem that you may have missed in the cacophony. This extends the standard/existing Google Search box that all FireFox installs have to include Google's AutoSuggest feature. With this you get a greatly enhanced without the emotional baggage of a new toolbar.
  • The MSN "Suite of Goo" aka MSN Search Toolbar - The MSN Toolbar has been updated and this time I took the plunge. Not for the Toolbar, no, I don't show it (right click, deselect), but for the Tabbed browsing. It's a hack, sure, and yes, I know there are a dozen browsers that host IE and offer tabs. I only use IE when I need oddpost, or visit the occassional site that hates FireFox, but when I do show up, I'd like to have tabs. Also, it's nice for my mom. Plus, the Desktop Search gets better and better. I've switched over from Google Desktop Search.
  • Del.icio.us Bookmarklets - Not exactly a toolbar, but I've dedicated space to Del.icio.us bookmarklets on ALL my PCs. What a brilliant and simple way to keep my bookmarks in one place. I save SO much more than I would with standard Bookmarks (which are a hassle to sync between n=browsers*PCs no matter what folks say. I haven't even dug into the social aspect of Del.icio.us. I'm too busy saving things!
  • GenPass Bookmarklet - A great little tool for creating complex passwords that are site specific. Generates passwords that you never see, so you can't give them up under torture. There's a feature I can be in support of. You never know when I could be tortured for my Google Adsense password. If I had a nickel...
  • Web Developer - OK, I didn't install it this week per se, but it's still wonderful. If you don't know what it is, and you have FireFox, go get it. If you don't have FireFox, it's the best reason ever to download FireFox. Run. Now.

It's getting to me quite the "me too" game with Microsoft and Google. Seems like when Google comes out with the Whatever.Google.com subdomain that Microsoft immediately offers the Whatever.MSN.com subdomain. Can't we all just get along?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Better Url for the Ultimate Tools List

July 08, 2005 Comment on this post [3] Posted in Musings | Tools
Sponsored By

FYI, there's now a better URL for the Ultimate Tools List - one you can store in your head. The latest version will always be at:

http://www.hanselman.com/tools/

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.