Wednesday, May 6, 2015

Tricky way to handle Form Authentications's redirection page in AngularJS Interceptor.


 Let me try to make you understand my problem.

     1)      I am using MVC Form Authentication to manage my application
     2)      In client Angular is being used , so I am using $http service heavily from all pages
     3)      Redirection URL for Unauthorized user is defined in config file in which is tradition way of implantation.

So, this is my implantation and my problem starts here. When user’s session is time out ASP.NET redirects user to particular page which I have defined in config file in Form Authentication tag. When user is posting back that’s working as expectd.

But when It’s AJAX call using $http service in Angular ,ASP.NET is processing the login page and returning with 200 status when user is not authenticated.

That’s the root cause of problem. Success callback of $http service is taking this as good response and showing content of login page in client.

If user is not authenticated when we should expect 401 rather than 200 in client If this is an AJAX call. I did little Search in Google and tried to intercept the HTTP request but no luck which worked fine with $.ajax of JQury.

Please let me know If you have code to check 401 when Form Authentication is in server and AngularJS $http is in client by using HTTP interceptor.

So, I have implanted this in little different way and I believe this is not much hacky J . If you have better suggesting, please let me know.

 First of all I have implanted custom Authorization filter where I am checking whether the call is AJAX call or not?
 public class myAuthorization : System.Web.Mvc.AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                base.HandleUnauthorizedRequest(filterContext);
            }
            else
            {
                if (filterContext.HttpContext.Request.IsAjaxRequest())
                {
                    filterContext.HttpContext.Response.StatusCode = 401;
                    filterContext.HttpContext.Response.End();
                }
            }
            base.OnAuthorization(filterContext);
        }
       
    }

 Action is decorated with custom authentication filter

[myAuthorization]
        public string Data()
        {
            return "data";
        }

In angular module I am detecting 401 response using Intercptor.

var app = angular.module("myApp", [])

        .factory('authHttpResponseInterceptor',['$q','$location',function($q,$location){
            return {
                response: function (response) {
                    if (response.status === 401) {
                    }
                    return response || $q.when(response);
                },
                responseError: function(rejection) {
                    if (rejection.status === 401) {
                        console.log("Response Error 401",rejection);
                        $location.path('/login').search('returnTo', $location.path());
                    }
                    return $q.reject(rejection);
                }
            }
        }]).

Here is code to set header to know ASP.NET that this call is AJAX call

        config(['$httpProvider', function ($httpProvider) {
            $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
        }])

It’s time topush the interceptor in $httpProvider service.

        .config(['$httpProvider',function($httpProvider) {
            $httpProvider.interceptors.push('authHttpResponseInterceptor');
        }]);

At last controller is to make AJAX in $http call.

app.controller("myController", function ($http, $scope) {

             $http({ method: 'GET', url: '/Home/Data' }).
               success(function (data, status, headers, config) {
                   alert(data);

               });
        });

And the problem solved.


Now If user post back then Form authentication will return page from server and If user make AJAX call then custom authentication filter will end response with 401 status code and Angular’s interceptor will handle the response. 

No comments:

Post a Comment