Scott Hanselman

CSI: ASP.NET - The one where a double HTTP GET from Internet Explorer (IE) causes problems with FormsAuthentication and my sanity

November 19, 2004 Comment on this post [8] Posted in ASP.NET | Movies | Javascript | Bugs | Tools
Sponsored By

Here's a weird one from the CSI: ASP.NET files...this is the weirdest DOUBLE HTTP GET bug, since, well, the last one.

Scenario:

  • On Brian's local machine as a user moves through an enrollment process in an ASP.NET Application, everything works fine. 
  • The user receives a valid ASP.NET SessionID, moves from page to page, logs in to Forms Authentication and receives a Forms Auth Cookie.
  • All is right with the world.

Problem Arises:

  • When the ASP.NET Application is deployed to a Dev machine (not Brian's machine) the whole process doesn't work. It seems that the user is getting a new, fresh Session each page view. The Forms Authentication Cookie never shows up, and the ASP.NET Session ID is always new.
    • Note: ASP.NET Session IS enabled on both machines, no cookie blocking or domain specific security exists.

Forensics:

  • I hear about this and Brian and I load up Jonas Blunck's ieHttpHeaders (I donated US$10 to him after this experience) to see what's really happening.
    • Opinion: I'm not a fan of Programming by Coincidence where you move code around at the highest level of abstraction, basically creating all sorts of invalid states so the system "mostly works" without ever finding out what the Root Cause is. A lot of the stuff I do at Corillian is Root Cause Analysis in the most informal sense. I can troubleshoot a problem for you and also use QEMM386 to load your device drivers into the UMB giving you up to 610k of main memory! These are the skills we pick up. :)
  • We load up the HTTP Headers on Brian's (working) local machine and see something like:
    • GET /myapp/login.aspx HTTP/1.1
    • 200 OK
    • Set-Cookie: ASPSessionID=1234...
    • GET /
    • 403 Forbidden
    • GET /myapp/nextstep.aspx
    • 200 OK
    • Set-Cookie: ASPSessionID=1234...
    • Set-Cookie: FormsAuth=mzxa...
    • GET /
    • 403 Forbidden
  • What the heck are those 403 Forbiddens? We are only requesting two pages. Why are we seeing two extra GETs?
  • So, we think:
    • Spyware - nope, we ran SpyBot. Clean.
    • GoogleToolbar - nope, it doesn't do that.
    • JavaScript - none on these pages that would change location.href
  • We then run HTTP Headers on the Dev (NON-working) machine and see this:
    • GET /login.aspx HTTP/1.1
    • 200 OK
    • Set-Cookie: ASPSessionID=1234...
    • GET /
    • 200 OK
    • Set-Cookie: ASPSessionID=4567...
    • GET /nextstep.aspx
    • 200 OK
    • Set-Cookie: ASPSessionID=1234...
    • Set-Cookie: FormsAuth=mzxa...
    • GET /
    • 200 OK
    • Set-Cookie: ASPSessionID=7890...
    • Set-Cookie: FormsAuth=""
  • Oy! The Session and Cookie are getting blown away by this mystery HTTP GET.
  • What's different on the Dev machine?
    • The ASP.NET Application is in the root directory, rather than in /myapp as on Brian's machine.
    • The ASP.NET Application allows anonymous users to access the root "/", while Brian's machine doesn't. It allows anonymous users to access /myapp.
    • The Default Document is set to /login.aspx on the Dev machine, while Brian's machine has no default document. When / is asked for on the Dev machine, /login.aspx will be retrieved.
  • What does an HTTP GET to /login.aspx do?
    • if (!IsPostBack)
      {
         Session.Abandon(); //Clean up personal info from the session
         FormsAuthentication.SignOut(); //Fresh cookies for a fresh login
      }
  • So, yes, requesting / from the Dev machine will execute /login.aspx which will blow away their session and FormsAuth cookie, but why is the HTTP GET / happening on every page?
  • What is the only thing that is shared between pages? The Footer.ascx page.
  • What's on that page? A bunch of tables, and some spacer images.
  • Spacer images you say? Oy, you mean 1-pixel gifs.
  • Ah! You WISH I meant 1-pixel gifs. I mean <img src="" width="1" height="1">

Coda:

  • IE will automatically issue one HTTP GET for "/" (the root of the domain) for every page that has an IMG tag with a empty src="".
  • Know what happens if when that request is served.

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 twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
November 19, 2004 14:09
nice post, it was a good reading :)
November 19, 2004 19:05
Interesting. ieHttpHeaders have also spared me from some grief in the past. I wich there was an official "IE Developers Edition" with all those helper toolbars that we end up using.
On another note, I never tried using spacers without the src, would have never suspect it would retrieve the root folder.
November 19, 2004 21:37
Doesn't that also show a broken image in downlevel browsers?
November 19, 2004 21:39
In VERY download (4.0,etc) yes. In Netscape and Mozilla since the size is 1x1, it shows nothing. It was apparently meant to avoid an extra IMG call for all those 1x1 pixel gifs when browser caching was turned off.
November 21, 2004 22:51
[SEMI-SARCASTIC]
And was that worth it? (no-image IMG)
[/SEMI-SARCASTIC]
November 22, 2004 0:15
I have used ieHTTPHeaders in the past as well.

Another similar tool which I really like is Fiddler. (http://www.fiddlertool.com/fiddler/)

-Scott
November 25, 2004 13:08
I'm fighting with a similar problem. Fiddler has trouble with proxies though, so I'm giving ieHttpHeaders a chance. It is awesome.
December 07, 2005 16:58
Hi there,

interesting reading. I see a double GET via ieHTTPHeaders when MSIE refuses to complete NTLM authorization. By using ethereal it is possible to see that only the second GET is actually sent. Its as if IE post-processes the request before sending to check validity.

It looks as if your double GETs are sent to the webserver, wish mine's was!!!

Comments are closed.

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