Jarrett's Tech Blog - For September 2012
-
Simple Fix for ASP.NET FormsAuthentication Redirect when using AJAX
There is one paticular annoying "feature" of ASP.NET forms authentication module that has kicked my butt many times. When a user loads a page but their session has expired, the module will take over the request and return a 302 redirect to the login page rather than the appropriate 401 unauthorized.
Specification of the correct behaviour has been part of the HTTP standard for more than 15 years now. HTTP 1.1, RFC 2616 (and before that, HTTP 1.0, RFC 1945) specify the correct behavior in sections 10.4.2 and 9.4 respectively (the verbiage hasn't changed significantly):
This "feature" has always been broken in ASP.NET and it has caused me countless hours of research and workarounds. Others have also dealt with the problem:
- Prevent Forms Authentication Login Page Redirect When You Don't Want It
- Basic Authentication with WCF Web API hosted in IIS / Getting a 404 - Disable Forms Authentication Redirection
- Prevent forms auth from redirecting to login page in RESTFul WCF
- AJAX and FormsAuthentication, how prevent FormsAuthentication overrides HTTP 401?
- How to Handle Forms Authentication Timeout During an AJAX Request
- How to intercept 401 from Forms Authentication in ASP.NET MVC?
Back in 2008, I used the HttpModule workaround as decribed in many of the above posts. I've also utilized an Application_OnError workaround. Unfortunately, many of these solutions require too much code, additional config, and/or tradeoffs.
I would prefer a fix directly to forms authentication, but Microsoft still hasn't addressed the problem. We could replace forms authentication with something like AppHarbor.Web.Security or MADAM. However, this can be scary to those who are unfamiliar with exercising options outside of those provided by Microsoft.
So that brings me to point of this post. How can we KISS and still fix the damn problem?
Add this to Global.asax.cs to fix the broken FromsAuthentication redirect behavior. This code will reset the 302 back to 401 for AJAX requests.
Add this javascript to your layout so that anytime you use jQuery ajax, get, or post, the client will detect the 401 and reload the page. This will cause the browser to redirect to login page.
That's all. Problem fixed with very few lines of code.