0
votes

I am currently implementing a simple user authentication and I want the user to only be able to view some states if the user is loggedin and the token is not null. This is because on my ionic app, when i refresh a state, it immediately goes to my default page even though the user has been logged in and the user has a token.

So in my app.js, i did the following to check if the user can go to the state,

    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {

$ionicLoading.show({
  template: 'Loading...'
});

if (window.sessionStorage.token) {
  $http.defaults.headers.common.Authorization = window.sessionStorage.token;  
  $rootScope.localTokenKey = window.sessionStorage.token;
  $rootScope.isLoggedin = true;
}
else {
  $rootScope.isLoggedin = false;
}

if(toState.data) {
  if(!$rootScope.isLoggedin){
    $state.transitionTo('login', {}, { reload: true, inherit: true, notify: true})
  }
} else {
  console.log("FAILED")
}

})

$rootScope.$on("$stateChangeSuccess", function(event, toState, toParams, fromState, fromParams){ $ionicLoading.hide(); });

state provider config This is the list of the states.

.config(function($stateProvider, $urlRouterProvider, $httpProvider) {


      $stateProvider
      //$controllerProvider.allowGlobals();

      .state('login', {
        url: "/login",
        templateUrl: "templates/login.html",
        controller: 'AppCtrl'
      })

      .state('app', {
        url: "/app",
        abstract: true,
        templateUrl: "templates/menu.html",
        controller: 'MainCtrl'
      })

      .state('app.dashboard', {
        url: "/dashboard",
        views: {
          'menuContent': {
            templateUrl: "templates/dashboard.html",
          }
        },
        authenticate : true
      })

      .state('app.case_status', {
        url: "/case_status",
        views: {
          'menuContent': {
            templateUrl: "templates/case_listing.html",
            controller: 'ReferralCtrl'
          }
        },
        authenticate : true
      })
      .state('app.case_status_single', {
        url: "/case_details",
        views: {
          'menuContent': {
            templateUrl: "templates/case_details.html",
            controller: 'ReferralCtrl'
          }
        },
        authenticate : true

      })

      .state('app.feedback', {
        url: "/feedback",
        views: {
          'menuContent': {
            templateUrl: "templates/feedback.html"
          }
        },
        authenticate : true

      })

      .state('app.new', {
        url: "/new_referral",
        views: {
          'menuContent': {
            templateUrl: "templates/new_referral.html",
            controller: 'NewCaseCtrl'
          }
        },
        authenticate : true
      })

      .state('app.settings', {
        url: "/settings",
        views: {
          'menuContent': {
            templateUrl: "templates/settings.html"
          }
        },
        authenticate : true
      })

      .state('logout', {
          url: "/logout",
          views: {
            'menuContent' : {
            }
          } 
      });

      // if none of the above states are matched, use this as the fallback
     //$urlRouterProvider.otherwise('/login');
    })

When i run my code, the console.log("login page") is executed more than 1000times before it hits an unidentified error then the login page is shown.

What am i doing wrong and how can i solve this issue. I am using AngularJS.

1

1 Answers

0
votes

Don't bother intercepting and preventing the state change if you don't need to do anything (ie, user is logged in).

Also, I'd change the logic to look for a public flag instead of your authenticate flag and assume all states require authentication. In fact, I'd say the fact that your "login" state evaluates toState.authenticate to false is the root of your problem.

Finally, extra state data should go in the data property.

To summarise

  1. Use a public flag on any state that is publicly available

    .state('login', {
        url: "/login",
        templateUrl: "templates/login.html",
        controller: 'AppCtrl',
        data: {
            public: true
        }
    })
    

    and remove the authenticate properties from the other states.

  2. Check for the public flag or $rootScope.isLoggedIn and go to your login state if both are false

    $rootScope.$on('$stateChangeStart', function(event, toState) {
        $ionicLoading.show({
          template: 'Loading...'
        });
    
        if (!((toState.data && toState.data.public) || $rootScope.isLoggedIn)) {
            console.log("login page")
            event.preventDefault(); 
            $state.transitionTo('login', {}, { reload: true, inherit: true, notify: true});
        }
    })