version 2
version 2

Reputation: 1059

AngularJS- logout from website not working

I'm developing a website using angularJS and PHP. Users can login if credentials are valid and if valid, PHP sets a session and returns a token which I store in localStorage.

I created a service which checks for authenticity of the token. I have a logout controller as well. But my logout feature is not working properly. I remove local storage token and destroy the session and I get navigated to index page but I can still view other pages my changing the URL.

This is my login controller

(function() {

  angular
    .module('myApp.login', [])

  .controller('LoginController', function($scope, $http, $location) {
    var vm = this;

    $scope.post = {};
    $scope.post.login = [];
    $scope.vm = {};
    $scope.index = '';

    var baseUrl = 'api/';

    // function to submit the form after all validation has occurred            
    vm.login = function(isValid) {
      // check to make sure the form is completely valid
      if (isValid) {
        $http({
            method: 'post',
            url: baseUrl + 'login',
            data: $.param($scope.vm),
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded'
            }
          })
          .success(function(data, status, headers, config) {
            if (data.success) {
              if (localStorage['token']) {
                localStorage.removeItem('token');
              }
              localStorage.setItem("token", JSON.stringify(data.login_token));

              $location.path('/home');
            } else {

              if (localStorage['token']) {
                localStorage.removeItem('token');
              }

              vm.errorMessage = data.msg;
            }
          }).
        error(function(data, status, headers, config) {
          if (localStorage['token']) {
            localStorage.removeItem('token');
          }
          vm.errorMessage = data.msg;
        });
      }
    };


  });

})();

Once login is successful, set a token. You can see that above And then I redirect user to Home Controller which looks like this:

-(function() {

    angular
      .module('myApp.home', [])

    .factory('myHomeService', function($http) {
      var baseUrl = 'api/';
      return {
        getUserSessInfo: function() {
          return $http.get(baseUrl + 'get_user_session');
        }
      };
    })

    .controller('HomeController', function($scope, $routeParams, myHomeService, AuthService) {
        var vm = this;
        var token;
        if (localStorage['token']) {
          token = JSON.parse(localStorage['token']);
        } else {
          token = "";
        }

        if (token) {
          AuthService.checkToken(token);

          //To get user session value
          myHomeService.getUserSessInfo().success(function(data) {
            vm.id = data.id;
            //vm.userName   = data.username;
          });

          $scope.logout = function() {
            var data = {
              token: token
            }
            AuthService.logOut(token);
          }

        });
    })();

In home controller, I check for the token and call the service AuthService which does user authentication.

Here is AuthService. It has two functions. One to check token and other to do logout.

(function() {

angular
.module('myApp.AuthenticationService', [])

.factory('AuthService', ["$http", "$location", function($http, $location){
    var vm = this;
    var baseUrl = 'api/';
    vm.checkToken = function(token)
    {        
        var data = {token: token};

        $http.post(baseUrl + 'validateUserToken', data).success(function(response)
        {
            if (response.msg === "unauthorized")
            {
                //console.log("Logged out");
                $location.path('/login');
            } 
            else 
            {
                //console.log("Logged In");
                return response.msg;
            }
        }).error(function(error)
        {
            $location.path('/login');
        })

    }

    vm.logOut = function(token)
    {        
        var data = {token: token};

        $http.post(baseUrl + 'destroyUserToken', data).success(function(response)
        {
            if (response.msg === "Logged out")
            {
                 localStorage.clear();
                //console.log("Logged out");
                $location.path('/login');
            } 
        }).error(function(error)
        {
                localStorage.clear();
            $location.path('/login');
        })

    }
   return vm;
}]);

})();

And when user click a logout link, logout controller is called. Here it is:

(function() {

  angular
    .module('myApp.logout', [])

  .controller('LogoutController', function($scope, $routeParams, AuthService) {
    var vm = this;

    //If user is not logged in
    var token;
    if (localStorage['entrp_token']) {
      token = JSON.parse(localStorage['entrp_token']);
    } else {
      token = "something stupid";
    }
    AuthService.logOut(token);

  });
})();

But even after doing all this, user can navigate to older pages by changing the url. How can i prevent this?

Upvotes: 1

Views: 1049

Answers (2)

Arif
Arif

Reputation: 1643

You can use resolve on your routes to find out if user is logged in or no before rendering the template.

check this Fiddle to have an idea how to do it

var onlyLoggedIn = function ($location,$q,Auth) {
    var deferred = $q.defer();
    if (Auth.isLogin()) {
        deferred.resolve();
    } else {
        deferred.reject();
        $location.url('/login');
    }
    return deferred.promise;
};


angular.module('YourModule')
.factory('Auth', function() {
var isLogin = function() {
console.log(localStorage.isLogged)
return localStorage.isLogged === "true";
}
return {isLogin: isLogin}
})

.config(function ($routeProvider) {
    $routeProvider.
    when('/home', {
        templateUrl: 'embedded.home.html',
        controller: 'HomeController'
    }).
    when('/about', {
        templateUrl: 'embedded.about.html',
        controller: 'AboutController',
        resolve: {loggedIn: onlyLoggedIn}
    }).
    otherwise({
        redirectTo: '/home'
    });
});

Upvotes: 1

jegtugado
jegtugado

Reputation: 5141

You would need to handle things during routing. When the user is not logged-in and the page requested requires otherwise, you should redirect to a different page such as 'Unauthorized.html' or something similar.

I'm using $routeProvider for routing. I haven't tried using angular ui-router so forgive me if this doesn't suit your needs.

I added a property loginRequired on my routing as well as requiredRoles to identify if the current user has access to a specific page.

Using $routeChangeStart I am checking if the page conditions is satisfied such as if the current user is logged-in and has authority to access the page. Failure to meet the conditions, I navigate to a different page.

Code extracted from my old project:

.config(["$locationProvider", "$routeProvider", "$httpProvider", "KeepaliveProvider", "IdleProvider",
            function ($locationProvider, $routeProvider, $httpProvider, KeepaliveProvider, IdleProvider) {

            var templateLocation = "/Templates";

            $locationProvider.html5Mode({
                enabled: true,
                requireBase: true,
                rewriteLinks: true
            }).hashPrefix("#");

            $routeProvider
                .when("/", {
                    templateUrl: templateLocation + "/Home.html", //"/Product-List.html", // 
                    controller: "HomeController", //"ProductController", // 
                    loginRequired: false,
                    requiredRoles: []
                })
                .when("/Report", {
                    templateUrl: templateLocation + "/Report.html",
                    controller: "ReportController",
                    loginRequired: true,
                    requiredRoles: ["Admin"]
                })
                .when("/About", {
                    templateUrl: templateLocation + "/About.html",
                    controller: "AboutController",
                    loginRequired: false,
                    requiredRoles: []
                })
                .when("/Contact", {
                    templateUrl: templateLocation + "/Contact.html",
                    controller: "ContactController",
                    loginRequired: false,
                    requiredRoles: []
                })
                .when("/Register", {
                    templateUrl: templateLocation + "/Register.html",
                    controller: "RegisterController",
                    loginRequired: false,
                    requiredRoles: []
                })
                .when("/Login", {
                    templateUrl: templateLocation + "/Login.html",
                    controller: "LoginController",
                    loginRequired: false,
                    requiredRoles: []
                })
                .when("/User-List", {
                    templateUrl: templateLocation + "/User-List.html",
                    controller: "UserController",
                    loginRequired: true,
                    requiredRoles: ["Admin", "Secretary"]
                })
                .when("/User-Profile/:userId", {
                    templateUrl: templateLocation + "/User-Profile.html",
                    controller: "UserController",
                    loginRequired: true,
                    requiredRoles: []
                })
                .when("/TermsAndCondition", {
                    templateUrl: templateLocation + "/Terms-And-Condition.html",
                    controller: "SupportController",
                    loginRequired: false,
                    requiredRoles: []
                })
                .when("/EmailConfirmed", {
                    templateUrl: templateLocation + "/EmailConfirmed.html",
                    controller: "SupportController",
                    loginRequired: false,
                    requiredRoles: []
                })
                .when("/ResetPassword", {
                    templateUrl: templateLocation + "/ResetPassword.html",
                    controller: "SupportController",
                    loginRequired: false,
                    requiredRoles: []
                })
                .when("/ForgotPassword", {
                    templateUrl: templateLocation + "/ForgotPassword.html",
                    controller: "SupportController",
                    loginRequired: false,
                    requiredRoles: []
                })
                .when("/Unauthorized", {
                    templateUrl: templateLocation + "/Unauthorized.html",
                    controller: "UnauthorizedController",
                    loginRequired: false,
                    requiredRoles: []
                })
                .when("/ErrorHandler", {
                    templateUrl: templateLocation + "/ErrorHandler.html",
                    controller: "ErrorController",
                    loginRequired: false,
                    requiredRoles: []
                })
                .otherwise({
                    templateUrl: templateLocation + "/Error404.html",
                    controller: "ErrorController",
                    loginRequired: false,
                    requiredRoles: []
                });

        }])             
 .run(["$q", "$rootScope", "$location", "AccountService", "Idle", function ($q, $rootScope, $location, AccountService, Idle) {

            Idle.watch();
            var templateLocation = "/Templates";
            var postLogInRoute;

            $rootScope.$on("$routeChangeStart", function (event, nextRoute, currentRoute) {
                if (AccountService.isLoggedIn() &&
                    (nextRoute.templateUrl == templateLocation + "/Register.html" ||
                    nextRoute.templateUrl == templateLocation + "/Login.html")) {
                    $location.path("/Unauthorized").replace();
                    postLogInRoute = $location.path();
                }
                else if (nextRoute.loginRequired && !AccountService.isLoggedIn()) {
                    $location.path("/Login").replace();
                    postLogInRoute = $location.path();
                }
                else if (nextRoute.templateUrl.length != templateLocation + "/Unauthorized.html" && !AccountService.isUserAuthorized(nextRoute.requiredRoles)) {
                    $location.path("/Unauthorized").replace();
                    postLogInRoute = $location.path();
                }
                //else if (postLogInRoute && AccountService.isLoggedIn()) {
                //    $location.path(postLogInRoute).replace();
                //    postLogInRoute = null;
                //}
                else {
                    // Do nothing
                }
            });

        }])

Upvotes: 0

Related Questions