3

I have a simple (half finished) http interceptor that appends a Bearer token (stored in $window.sessionsStorage) to the header so that REST API requests can be authenticated:

function accessTokenHttpInterceptor($window, $http) {

  // Try to get token details from sessionStorage
  var accesstoken=$window.sessionStorage.getItem('userInfo-accesstoken');
  var refreshtoken=$window.sessionStorage.getItem('userInfo-refreshtoken');
  var tokenexpiry=$window.sessionStorage.getItem('userInfo-tokenexpiry');

  return {

    request: function($config) {

      // Check if the access token, refresh token and expiry date exists:
      if (accesstoken == undefined || refreshtoken == undefined || tokenexpiry == undefined) {
        console.log('Missing token details');
        // TODO REDIRECT TO LOGIN PAGE
      }

      // We have an access token. Has it expired?
      var expiry = new Date($window.sessionStorage['userInfo-tokenexpiry'])
      var now = new Date
      if (now > expiry ) {
        console.log('Token expired');
        // TODO REFRESH THE TOKEN
        };

      // Set the authorization header
      $config.headers['Authorization'] = 'Bearer ' + accesstoken;
      return $config;

    },
  };
}

accessTokenHttpInterceptor.$inject=['$window'];

function httpInterceptorRegistry($httpProvider) {
    $httpProvider.interceptors.push('accessTokenHttpInterceptor');
}

angular
    .module('myApp')
    .config(httpInterceptorRegistry)
    .factory('accessTokenHttpInterceptor', accessTokenHttpInterceptor)

As you can see, I am able to see if the token has expired prior to making the call to the API.

Can anybody help me with how to refresh the token prior to making the actual API request? I would think that making another $http request would be intercepted again and end up in an infinite loop. The token is refreshed by making a POST request to the API, where the refresh token is passed as a parameter, not in the Authorization header like other API requests.

1 Answer 1

2

You could check the url of the request to prevent an infinite loop. Also instead of returning the config directly you could return a promise that resolves with it so you can wait until you have a valid token. e.g.

{
    request: function(config) {
        if(config.url != 'my/refresh/url') {
            var promiseToHaveValidToken;

            var expiry = new Date($window.sessionStorage['userInfo-tokenexpiry']);
            var now = new Date();
            if (now > expiry ) {
                promiseToHaveValidToken = $http.get('my/refresh/url').then(function (response) {
                    return response.data.token;
                });
            } else {
                promiseToHaveValidToken = $q.resolve(sessionStorage['userInfo-accesstoken']);
            }

            return promiseToHaveValidToken.then(function (token) {
                config.headers['Authorization'] = 'Bearer ' + token;
                return config;
            });
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

using $http inside the interceptor gives a circular reference error
Right, you have to const $http = $injector.get('$http');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.