1

I am building a project in ionic and I need to send jwt tokens with each request. I am a total angular newbie and I wonder where I need to place the logic for http interceptors. Where should I do that, should I put that inside config part, make a new service or something else?

This is the interceptor logic I need to insert:

$httpProvider.interceptors.push(['$q', '$location', '$localStorage', function ($q, $location, $localStorage) {
   return {
       'request': function (config) {
           config.headers = config.headers || {};
           if ($localStorage.token) {
               config.headers.Authorization = 'Bearer ' + $localStorage.token;
           }
           return config;
       },
       'responseError': function (response) {
           if (response.status === 401 || response.status === 403) {
               $location.path('/signin');
           }
           return $q.reject(response);
       }
   };
}]);

This is the config part in my app.js:

.config(function($stateProvider, $urlRouterProvider, $authProvider, ApiEndpoint) {

  $authProvider.loginUrl = ApiEndpoint.url + '/authenticate';

  $stateProvider
  .state('main', {
    url: '/main',
    abstract: true,
    templateUrl: 'templates/main.html'
  })

  .state('main.auth', {
    url: '/auth',
    views: {
      'content': {
        templateUrl: 'templates/login.html',
        controller: 'AuthController'
      }
    }
  })

  .state('main.front', {
    url: '/front',
    views: {
      'content': {
        templateUrl: 'templates/main-front.html',
        controller: 'FrontPageController'
      }
    }
  })

  .state('main.article', {
    url: '/article/{id}',
    views: {
      'content': {
        templateUrl: 'templates/main-article.html',
        controller: 'ArticleController'
      }
    }
  });

  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/main/front');
});

I have added it to services.js like this, I wonder if this is the right approach?

Updated code

services.js

angular.module('coop.services', [])

.factory('ArticleService', function($http, ApiEndpoint) {

  return {
    all: function() {
       return $http.get(ApiEndpoint.url + "/articles/latest").then(function(response){
             articles = response.data;
             return articles;
          });
       },
    get: function(id) {
      return this.all().then(function(response) {
        var articles = response;
        for (var i in articles) {
          if (articles[i].id == id) {
            return articles[i];
          }
        }
        return {};
      })
    }
  };
})

.factory('AuthenticationInterceptor', function RequestInterceptor($q, $location, $localStorage, $rootScope, CoreConfig) {
    var service = this;

    service.request = function (config) {
      config.headers = config.headers || {};
         if ($localStorage.token) {
             config.headers.Authorization = 'Bearer ' + $localStorage.token;
         }
         return config;
     };

    service.responseError = function (response) {
      if (response.status === 401 || response.status === 403) {
             $location.path('/signin');
         }
         return $q.reject(response);
    };

    return service;
});

.config part in app.js:

.config(function($stateProvider, $urlRouterProvider, $authProvider, ApiEndpoint, $httpProvider) {

  $httpProvider.interceptors.push('AuthenticationInterceptor');
  $authProvider.loginUrl = ApiEndpoint.url + '/authenticate';

  $stateProvider
  .state('main', {
    url: '/main',
    abstract: true,
    templateUrl: 'templates/main.html'
  })

  .state('main.auth', {
    url: '/auth',
    views: {
      'content': {
        templateUrl: 'templates/login.html',
        controller: 'AuthController'
      }
    }
  })

  .state('main.front', {
    url: '/front',
    views: {
      'content': {
        templateUrl: 'templates/main-front.html',
        controller: 'FrontPageController'
      }
    }
  })

  .state('main.article', {
    url: '/article/{id}',
    views: {
      'content': {
        templateUrl: 'templates/main-article.html',
        controller: 'ArticleController'
      }
    }
  });

  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/main/front');
});

2 Answers 2

0

The Interceptors are usually configured at the bootstrapping phase.
I tend to handle it under the app config:

appName.config(["$httpProvider", ($httpProvider: ng.IHttpProvider) => {
                $httpProvider.interceptors.push(() => {

               // Your interceptor's logic here

           });
       });
Sign up to request clarification or add additional context in comments.

1 Comment

Could you show that please on my example how to do that in my app.js?
0

"An interceptor is simply a factory() service that returns an object with 4 properties that map to functions". So write your interceptor as a normal service with which methods you need overide (request, response, requestError, responseError).

In code example below, I just care to request and respondError property so I just return a service with two propertis. You can also made many interceptors to handle each kind of these property. Many interceptors can be applied to only one property (some kind of interceptor: authentication, handle error, restore request, pre-process response/request data...).

app.factory('AuthenticationInterceptor', function RequestInterceptor($rootScope, CoreConfig) {
    var service = this;

    service.request = function (config) {
        if (angular.isDefined(CoreConfig.TokenKeyString) && angular.isDefined(CoreConfig.SessionKeyString)) {
            config.headers['Authorization-Token'] = CoreConfig.TokenKeyString;
            config.headers.SessionKeyString = CoreConfig.SessionKeyString;
        }
        return config;
    };

    service.responseError = function (response) {
        return response;
    };

    return service;
});

then push your interceptor at config phase:

appp.config(['$httpProvider', function ($httpProvider) {
     $httpProvider.interceptors.push('AuthenticationInterceptor');
}]);

6 Comments

I am not sure how to implement this in my code, I have updated my question with what I have tried to do so if you could have a look?
almost ok, just ensure that RequestInterceptor match your logic. and remove CoreConfig(my service), $location... if you don't need it for your interceptor.
I did that but then I get: ionic.bundle.js:13438 Uncaught Error: [$injector:unpr] Unknown provider: $localStorageProvider <- $localStorage <- AuthenticationInterceptor <- $http <- $templateFactory <- $view <- $state
You need add local storage to your app medium.com/@petehouston/…
when I write localStorage without the $ sign everything works, and I think since I am using satellizer that satellizer intercepts http requests and inserts token by default
|

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.