A
A
Artem Verbat2017-06-16 21:06:11
Angular
Artem Verbat, 2017-06-16 21:06:11

How to properly validate a token when requesting a template?

The client application is located separately from the server with the API. Accordingly, the question arose of how to control access to templates. I decided to make a request to the API, before loading the template, sending the token for verification.
How implemented:

app.run(function($rootScope, $state, AuthService) {
  let transitionIsAllowed = false;
  
  $rootScope.$on('$stateChangeStart', (event, toState, toParams) => {  
    if (toState.authenticate && !transitionIsAllowed) {
      event.preventDefault();
  
      AuthService.confirmToken().then(response => {
        transitionIsAllowed = true;
        $state.go(toState, toParams);
      }, error => {
        console.log(error);
        $state.go('logout');
      });
    }
  });

  $rootScope.$on('$stateChangeSuccess', () => {
    transitionIsAllowed = false;
  });
});

It is working. Not bad. An error occurs:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!

The code is executed many times, which leads to problems in other parts of the application.
Question: How normal is my version for solving the problem, what to fix in order to get rid of the error?
The second implementation option, through the http interceptor:
function ($q, $injector, AuthToken) {
  return {
    request: function (config) {
      if (
        (config.url.indexOf('views/app/dashboard') === 0) ||
        (config.url.indexOf('views/app/cabinet') === 0)
      ) {
        const deferred = $q.defer();

        $injector.get('AuthService').confirmToken().then(function () {
          deferred.resolve(config);
        }, function () {
          deferred.reject(config);
        });

        return deferred.promise;
      }

      return config;
    },
    responseError: function (response) {
      if (response.status === 401 || response.status === 403) {
        $injector.get('$state').go('logout');
      }

      return $q.reject(response);
    }
  };
}

This option works. But in the case when the token is not valid, the following is displayed:
Error: [$compile:tpload] Failed to load template: views/app/dashboard/dashboard.html (HTTP status: undefined undefined)

Why? How to fix?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
O
ozknemoy, 2017-06-17
@ozknemoy

it looks like the $state.go inside confirmToken fires a new $stateChangeStart event and the result is an infinite loop. it is necessary either to block the logic in the resolve of each state, but this is a lot of writing code. or don't do event.preventDefault() and after confirmToken fails just redirect to home/do $state.go('logout'). you can also try to return event.preventDefault() in the promise, but probably the state will still have time to change

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question