57

I have a back-end server written in asp.net mvc using Forms Authentication. When the user is not authenticated, the server will automatically send a 302 redirect to a Login action and return a Login page.

On client side, I have a list of items. This list is only accessible to authenticated users. On the page, I have a button to Refresh the list using Ajax ($.ajax function of jQuery).

Now, my problem is when the authentication ticket is timeout and the user clicks on the Refresh button:

  • My function sends an ajax request to get the refreshed list
  • The server detects that the authentication ticket is not valid and issues a 302 redirect.
  • The browser automatically handles that 302 response and forces my ajax function to send another ajax request to the Login action and the final result is an HTML with status 200. My script is confused because the list is also an HTML with status 200.

What I want is when the authentication ticket is timeout and the user clicks on the Refresh button, I should be able to detect that and display a message asking the user to Login.

I tried to workaround this by adding a custom header (IS_LOGIN) in the Login action and check that in my ajax response. But it is not a good solution.

So my questions are:

  • What is the best way to deal with this problem?
  • Why does the browser not let our script handle 302 response? and just automatically forces our ajax to create another request. This is a problem with the browser or jquery library? Any reasons for this? (security,...)

Thanks for any replies.

Khanh TO
  • 48,509
  • 13
  • 99
  • 115

1 Answers1

48

You shouldn't redirect the call when it's an XHR but respond with a 401 Unauthorized and handle this in your callbacks. I don't know ASP.NET but I did something similar with Spring Security.

Heres the concept:

  • Get the authenticated state
  • Check the headers for X-Requested-With: XMLHttpRequest
  • When found and not authenticated respond with 401 Unauthorized
  • When not found and not authenticated redirect.

The bottom line is that XHR calls need to be handled differently then other HTTP requests in some cases. You should only redirect a XHR if the same resource is at another location.

To answer your question

You can't handle redirects with XHR callbacks because the browser takes care of them automatically. You will only get back what at the redirected location.

Community
  • 1
  • 1
Bart
  • 17,070
  • 5
  • 61
  • 80
  • Thanks for your response. Do you mean we use 302 for normal requests and we only use 401 (or any unused status code) for ajax requests? – Khanh TO Apr 14 '13 at 08:13
  • 2
    My big question was : why we cannot handle 302 in ajax? Any reasons behind this? – Khanh TO Apr 14 '13 at 08:13
  • I know that the request is handled automatically as I already said that in my question. But Why ? – Khanh TO Apr 14 '13 at 08:24
  • 4
    Because that's the nature of a redirect. See **4.6.7 Infrastructure for the send() method** in http://www.w3.org/TR/XMLHttpRequest/#the-send()-method for more info. – Bart Apr 14 '13 at 08:32
  • That's from W3C, still wonder why they don't let us handle 3xx response codes ourselves. – Khanh TO Apr 14 '13 at 09:04
  • 1
    Why? There's only one way to respond correctly to a redirect. And that's redirecting the request. Doing anything else (like catch it and show a form) just makes no sense. That's why you need to respond with a `401`. That way you'll **know** that authorization is required. `302 Found` doesn't say anything about authentication. – Bart Apr 14 '13 at 09:20
  • But at least we should be able to handle that in case we want to redirect the page: window.location.href for example – Khanh TO Apr 14 '13 at 09:29
  • 6
    **No you really should not.** A HXR should either get the resource or be told why not. You can act on the **why not** part in your code. If it was told that the resource is somewhere else it would not give much context. You'll need to separate the concept of a XHR request and a user visiting a page. – Bart Apr 14 '13 at 10:12