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();
}]
}
}
}
})
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');
});
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);
});
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With