Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Redirect with UI Router When Session Expires in Firebase

I'm using Angular with Firebase and UI Router. I'm using anonymous authentication. When a session expires, I would like the unauthenticated user to be redirected to the homepage. I've used the Yeoman Angularfire Generator as a model. But when I use the code below, an authenticated page does not redirect when a user is already on that page and the session expires.

.config(['$urlRouterProvider', 'SECURED_ROUTES', function($urlRouterProvider, SECURED_ROUTES) {
    $urlRouterProvider.whenAuthenticated = function(path, route) {
        route.resolve = route.resolve || {};
        route.resolve.user = ['Auth', function(Auth) {
            return Auth.$requireAuth();
        }];
        $urlRouterProvider.when(path, route);
        SECURED_ROUTES[path] = true;
        return $urlRouterProvider;
    };
}])
.run(['$rootScope', '$location', 'Auth', 'SECURED_ROUTES', '$state',
    function($rootScope, $location, Auth, SECURED_ROUTES, $state) {

        Auth.$onAuth(check);

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

            if (error === 'AUTH_REQUIRED') {
                $state.go('home');
            }
            else {
                console.log('authenticated');
            }
        });

        function check(user) {

            if (!user && authRequired($location.path())) {

                $state.go('home');
            }
        }

        function authRequired(path) {
            return SECURED_ROUTES.hasOwnProperty(path);
        }
    }
])
.constant('SECURED_ROUTES', {});

Router

.state('selection', {
    url: '/selection',
    authRequired: true,
    views: {

        'list': {

            templateUrl: 'app/views/project-list.html',
            controller: 'ProjectListCtrl as projectList',
            resolve: {    
              'user': ['Auth', function(Auth) {
                  return Auth.$waitForAuth();
               }]
             }
        },
        'selectionlist': {

            templateUrl: 'app/views/selection-list.html',
            controller: 'SelectionListCtrl as selectionList'
            resolve: {    
              'user': ['Auth', function(Auth) {
                  return Auth.$waitForAuth();
               }]
             }
        }
    }
})
like image 337
Ken Avatar asked Sep 06 '15 20:09

Ken


3 Answers

This is a common problem in Single Page Applications. With Angular you can solve it with $http interceptor.

The idea is if the session is expired the first time when the user needs some action from the backend to be redirected to the login page. Expired session is detected from the response itself.

Example:

.factory('httpAuthInterceptor', function ($q) {
  return {
    'responseError': function (response) {
      // NOTE: detect error because of unauthenticated user
      if ([401, 403].indexOf(response.status) >= 0) {
        // redirecting to login page
        $state.go('home');
        return response;
      } else {
        return $q.reject(rejection);
      }
    }
  };
})

.config(function ($httpProvider) {
  $httpProvider.interceptors.push('httpAuthInterceptor');
});
like image 154
S.Klechkovski Avatar answered Oct 24 '22 01:10

S.Klechkovski


Have you read through this?

https://www.firebase.com/docs/web/libraries/angular/guide/user-auth.html

I'd read the "Authenticating with Routers" section.

Edit

In that case you can grab the 'expires' value from Auth.$getAuth() and use it in a $timeout on $routeChangeSuccess. Essentially creating a countdown to session timeout after every route change...like so:

$rootScope.$on("$routeChangeSuccess", function() {
    var sessionTimeout = Auth.$getAuth().expires * 1000;
    var d = new Date();
    var n = d.getTime();

    var timer = sessionTimeout - n;

    console.log(timer);

    $timeout(function() {
        $location.path("/");
    },timer);
});
like image 3
jbdev Avatar answered Oct 24 '22 02:10

jbdev


As you said "when a user is already on that page and the session expires.", that case you can use

$location.path('/home')

And for auto detect idle session expiration Ng-Idle, see the demo

like image 1
Ali Adravi Avatar answered Oct 24 '22 00:10

Ali Adravi