How to prevent states from accessing through browser backward/forward buttons

52 views Asked by At

My application has three states A, B, C. State A asks for authentication. If we successfully logged in then we move to state B(ie. A->b). Then we can move to C from that state. But, if we logout at state C we redirect to state A as B and C pages require authentication. But, when we press browser back button states B and C are accessible. I want to remove these states from browser back/forward buttons.

I am using ui-router. I have used $stateChangeStart to recognize those pages which require authentication and stopped to access those pages. But, that solution doesn't look correct. Is there any way to do this using history management or something else.

Sample code:

My routes:

$stateProvider
    .state('account', {
            url: '/account',
            params: {isStateAuthorized: false},
            views: {
                'mainView@':{
                    templateUrl: 'pages/dashboard/dashboard.html',
                    controller: 'accountController' 
                }

            }
    })
    .state('account.accountDetails', {
            url: '/:accountType',
            params: {isStateAuthorized: false},
            views: {
                'mainView@':{
                    templateUrl: 'account/details/account-details.html',
                    controller: 'accountDetails'                       
                }
            }
    })
    .state('account.accountRegister', {
            url: '/:accountType/register',
            params: {isStateAuthorized: false},
            views: {
                'mainView@':{
                    templateUrl: 'account/registration/registration.html',
                    controller: 'registrationController'
                }
            }

    })

I have some other routes too like 'login' etc..

In .run method:

$rootScope.$on('$stateChangeStart', function(event, toState  , toParams, fromState, fromParams)
    {
        if(toState.params.isStateAuthorized === true && !$rootScope.isAppLog ) {
            event.preventDefault();
            $state.go('login');
        }
    });

Iam checking whether the state requires authentication or not using isStateAuthorized in params of each state.

Thanks.

1

There are 1 answers

0
Vladimir M On

I am not sure if event in ui-router is supporting the same API as generic ui events.

While it is possible to use the state change events to verify the authorization status and change to some other state if status is not correct, it is not very robust and may create some unwanted effects in history, for example.

Cleaner way is to use the resolve attribute for the state to make sure that authorization is present.

$stateProvider.state('some_state_that_needs_auth', {
    ... other state properties ...
    resolve:{
        $state:'$state',
        authSvc:'authService',
        isAuthorized:function($state, authSvc){
            if( !authSvc.isAuthenticated() ){
                 $state.go('login');
            }
        }
    }
})