AJAX Form Authentication and POST Requests

We have an ASP.NET application protected by form authentication. The application makes heavy use of MS AJAX to invoke its web services.

When the forms authentication time is up and GET -request occurs - everything is in order (the user is redirected to the login page).

BUT , when the forms and POST -request authentication time occurs (ajax) - redirection does not occur, instead the application returns “401 unathorized” and browser prompts for the username and password (and not for the login form, but the browser built into the browser ) Of course, entering ANY username / password never helps.

How can I do it?

UPDATE: After I looked with firebug, I just found out that regular POST requests redirect to login, these are just web service calls that call “401 Unauthorizes”. The difference between a regular request and a web service is the URL. What is "page.aspx" for regular post-request and "service.asmx / MethodName" for web services ...

+6
forms-authentication
source share
2 answers

Ok, answering my own assignments.

After studying this problem and studying a little more, I found that when a web application is protected using Forms-Authentication and the user is not authenticated , this happens:

  • If this is a GET request, the user is redirected to the login page.
  • If this is a POST request to the page, the user is redirected to the login page.
  • If this is a Web service POST request, the user receives 401-unauthorized

How ASP.NET Works

And if the web service is called by AJAX (xmlHttpRequest object) and returns 401 - of course, the browser shows a login popup.

Now, what you have to do is add code to Application_PostAuthenticateRequest, which will prevent a 401 cast for web services.

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) { if (Request.RequestType == "POST" //if its POST && !User.Identity.IsAuthenticated //if user NOT authed && !HasAnonymousAccess(Context) //if it not the login page ) { //lets get the auth type Configuration config = WebConfigurationManager.OpenWebConfiguration("~"); SystemWebSectionGroup grp = (SystemWebSectionGroup)config.GetSectionGroup("system.web"); AuthenticationSection auth = grp.Authentication; //if it FORMS auth if(auth.Mode== AuthenticationMode.Forms) { //then redirect... this redirect won't work for AJAX cause xmlHttpRequest can't handle redirects, but anyway... Response.Redirect(FormsAuthentication.LoginUrl, true); Response.End(); } } } public static bool HasAnonymousAccess(HttpContext context) { return UrlAuthorizationModule.CheckUrlAccessForPrincipal( context.Request.Path, new GenericPrincipal(new GenericIdentity(string.Empty), null), context.Request.HttpMethod); } 
+2
source share

I see two solutions:

(1) The mechanism of "heartbeat". On each page there is a script that will "ping" the server with some fictitious ajax request, for example:

 <script> setInterval(ping, 60000); // based on comment by John function ping() { $.get('/do/nothing'); } </script> 

Therefore, the session should not expire while the browser window is open.

(2) In each ajax request, check the status of the response. If the response contains a “401 unauthorized” code (or any other code other than 200), this means that the session has expired, and instead of loading the response into a dialog box on the page, redirects the user to the login page.

Conclusion based on comments:

The best solution would be to combine the two above mechanisms. The Heartbeat mechanism will help to keep the session as long as the page is displayed in the browser. But this does not guarantee it for sure. When the session ends, the connection to the server may be broken and resumed. So you should check the status of the response anyway.

+1
source share

All Articles