Sunday, 1 July 2007

Always Use Response.End() After FormsAuthentication.RedirectToLoginPage()

Here's something else that wasn't immediately apparent to me:

If you’re using FormsAuthentication.RedirectToLoginPage() to direct unauthenticated users to a login page, you must follow that statement with a Response.End() if the page would otherwise continue loading content. Although the code appears to branch, the redirect does not stop the execution of the rest of the page.

Redirects appear to work fine in a browser (and would pass all UI tests). They issue an “object moved” status, causing the browser to reload a new page. However, this reload relies on the client’s browser taking this action. If you inspect the response (eg. using telnet), you'll see that when browsing to a protected page, which has the redirect in the Page_Load handler, the “object moved” flag is correctly set, but the content following FormsAuthentication.RedirectToLoginPage() continues to be output, completely negating the purpose of log-in.

The solution is to add Response.End() after the redirect. The output is then correctly terminated as the following telnet session shows (click on the image to view it in full):

Screen shot of a command line telnet session

7 comments:

dege said...

Thanks for the tip. That is very scary to think that all the times I've used that call the rest of the page was sent to the client anyways. FormsAuthentication.RedirectToLoginPage should at least have an option to end the response immediately like Response.Redirect does.

ckelley said...

Neil,

Thank you so much for the Response.End advice. I've been developing ASP.NET apps for years and didn't notice until today that my RedirectToLoginPage wasn't stopping the current page from executing. Makes me wonder what else I don't know ;-)

Perry said...

Thanks for the information, been driving me crazy for two days on why the rest of the page code continued to process!!!

bm_hitter44 said...

Wow! I was searching on the net for exactly this. Once I realized what this was doing I thought "surely not" and sure enough it does! I have a feeling this is a common security hole on a lot of sites!!! Thanks for the heads up.

George said...

I'd like to point out that another method, if you don't want to use Response.End(), is to wrap your page load logic in a IsAuthenticated() if block.

The Van said...

Good stuff Neil! This is exactly what I was looking for. It's quite an oversight on the part of the ASP.NET dev team. Thanks again!

Christian Schiffer said...

Thank you its a great posting. I have programmed asp.net since beta 1.0 and never new this, I just knew that ResponseRedirectToLoginPage did not work as expected and never uses it, creating my own rutine with a response.redirect with the apropriate querystring instead.

Microsoft should have implementet a response.end() method call by default inside the ResponseRedirectToLoginPage() method as it is what the method name suggest the method will do.

Truthfully I don't see any reson of why one would not want that behaiviour, anyone care to comment? I mean if an optional responseEnd parameter is needed?