Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unauthorized result in ajax requests

Tags:

I have application with many ajax actions (implemented using JQuery.ajax), that returns JSON ot html. Some of them should be accessible only to authorized users, and I decorated them with [Authorize] attribute. For not ajax actions, if user not authorized - system redirects him to login page (that configured in web.config).

But this is not applicable for ajax actions, because if user was authorized - he load page, after that cookie expires and he is not authorized, and instead of html block, that should replace old, he get my login page inside block.

I know that I can solve this problem manually, for example remove [Authorize] attribute, and return special json/empty html, if user no authorized. But I dislike this solution, because I need to rewrite all my actions and ajax functions. I want global solution, that allow me not to rewrite my actions (may be custom authorize attribute, or some http unauthorized result custom handling).

I want to return status code, if request is ajax, and redirect to login page, if request isn't ajax.

like image 465
Evgeny Levin Avatar asked Mar 07 '12 20:03

Evgeny Levin


People also ask

What is processData false in Ajax?

processData. If set to false it stops jQuery processing any of the data. In other words if processData is false jQuery simply sends whatever you specify as data in an Ajax request without any attempt to modify it by encoding as a query string.


2 Answers

Add an Application_EndRequest handler to your code in global.asax.cs that modifies any 302 error (redirect to login page) to an 401 (unauthorized) error for an AJAX request. This will allow you to simply leave your controller actions as they are and handle the redirect (you really can only have the user login again if they aren't currently) via the client.

protected void Application_EndRequest()
{
    // Any AJAX request that ends in a redirect should get mapped to an unauthorized request
    // since it should only happen when the request is not authorized and gets automatically
    // redirected to the login page.
    var context = new HttpContextWrapper( Context );
    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
    {
        context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}

Then in your _Layout.cshtml file add a global AJAX error handler that redirects to your login action when it gets a 401 response.

<script type="text/javascript">
    $(function () {
        $(document).ajaxError(function (e, xhr, settings) {
            if (xhr.status == 401) {
                location = '@Url.Action( "login", "account" )';
            }
        });
    });
</script>

You might also want to try some of the techniques outlined in Phil Haack's blog, Prevent Forms Authentication Login Page Redirect When You Don’t Want It

like image 85
tvanfosson Avatar answered Sep 22 '22 13:09

tvanfosson


You don't have to rewrite all your actions, just create a custom filter to replace the builtin Authorize filter.

Other people have done it before

asp.net mvc [handleerror] [authorize] with JsonResult?

like image 34
Wiktor Zychla Avatar answered Sep 22 '22 13:09

Wiktor Zychla