0

I'm doing some onStateChange authorization like this:

angular
    .module('app')
    .run(['$rootScope', '$state', 'Auth', function ($rootScope, $state, Auth) {

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

            console.log(toState);

            if (!Auth.authorize(toState.data.allow)) {

                console.log("Not authorized");
                $state.go('app.auth.login', { redirect: toState.name });
            }

            console.log('Authorized');
        });

    }]);

Now, when I go to an unauthorized route, it acts as it should, up to a point. The authorization fails and it tries to redirect to app.auth.login. This is shown in the console.logs:

Object {url: "/", templateUrl: "modules/live/index.html", name: "app.live.index", data: Object}
app.routes.js:225 Not authorized
app.routes.js:222 Object {url: "/auth/login?redirect", templateUrl: "modules/auth/login.html", controller: "LoginController", name: "app.auth.login", data: Object}controller: "LoginController"data: Objectname: "app.auth.login"templateUrl: "modules/auth/login.html"url: "/auth/login?redirect"__proto__: Object
app.routes.js:229 Authorized
app.routes.js:229 Authorized

But the URL stays at the original state (the first attempted state), and I don't see the login screen. The LoginController never gets called (there's a console.log at the start that doesn't show.

If I visit /auth/login I see the login screen as intended.

Here's my app.routes.js:

/*****
* Auth
******/
.state('app.auth', {
    abstract: true,
    url: '',
    template: '<div ui-view></div>',
    data: {
        allow: access.everyone
    }
})

.state('app.auth.login', {
    url: '/auth/login?redirect',
    templateUrl: 'modules/auth/login.html',
    controller: 'LoginController'
})

.state('app.auth.logout', {
    url: '/auth/logout',
    controller: 'LogoutController'
})

/*****
* Live
******/
.state('app.live', {
    abstract: true,
    url: '/live',
    data: {
        allow: access.live
    }
})

.state('app.live.index', {
    url: '/',
    templateUrl: 'modules/live/index.html'
});

What can be causing this odd behaviour?

babbaggeii
  • 7,577
  • 20
  • 64
  • 118
  • I think you should use resolve(promises) instead of "stateChangeStart". Because stateChangeStart also creates problem when you refresh page – niran Mar 26 '15 at 15:51

1 Answers1

0

It happens in this cases, that we do forget to solve situation:

  • user is already (previously) redirected === user is going to $state.go('app.auth.login') ... no need to redirect

And we should not redirect in such case:

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

   if (toState.name === 'app.auth.login')
   {
     // get out of here, we are already redirected
     return;
   }

And once we do decide to redirect, we should stop current navigation with event.perventDefault();

    if (!Auth.authorize(toState.data.allow)) {
        // here
        event.perventDefault();
        $state.go('app.auth.login', { redirect: toState.name });
    }
    ...

See more for example in this $stateChangeStart event continuing after state change or that Q & A with a working plunker

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335