Unauthorized result in ajax requests

14,930

Solution 1

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

Solution 2

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?

Share:
14,930
David Levin
Author by

David Levin

I'm professional C#/.NET developer, mostly focused on ASP.NET Core.

Updated on July 01, 2022

Comments

  • David Levin
    David Levin almost 2 years

    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.

  • cnom
    cnom over 7 years
    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest() && context.Response.RedirectLocation.StartsWith("/Account/Login‌​")) I suggest adding the RedirectLocation in the condition, or else it might catch some other redirections and return unauthorized... which would not be desired..