1

I am working on angular project. When I login to application, I am saving access_token received from the login service in to $cookies. This access_token gets expires after 2 mins. After login, for subsequest functionality, I have to send this access_token to the service using $http to get valid response. Once this access_token gets expires after 2 mins, I am calling to a service which will regenerate access_token and again saving in $cookies. Without access_token, my other functionalities won't work.

Basically I need to check if access token present in $cookies or not before every service call in the application. If access token is not present, then Need to regenerate it with another service call using $http and save it back in cookies and then the desire service call of the functionality. and If access token present then do the desire service call.

my one of functionality is :

mPosController.controller('offerController', ['$scope', '$route', '$cookies', '$rootScope', 'mosServiceFactory', 'ngDialog', '$modal', '$q', function ($scope, $route, $cookies, $rootScope, mosServiceFactory, ngDialog, $modal, $q) {

       mosServiceFactory.viewAllOffers('page=0').then(function (data) {
                //Do the desire functionality
            });
   }]);

My services are :

mPosServices.factory('mosServiceFactory', function ($http, $rootScope, $cookies,$q) {
    return{
        viewAllOffers: function (page) {
            var allOffers = $http({
                method: "get",
                url: "myserviceurl?enrollmentId=" + $rootScope.enrollMentId + "&" + page + "&size=10&access_token=" + $cookies.get('access_token'),
            });
            return allOffers;
        },
        refresh_token: function () {
            var refreshToken = $http({
                method: "get",
                url: "myserviceurl/oauth/token?grant_type=refresh_token&client_id=restapp&client_secret=restapp&refresh_token=" + $cookies.get('refresh_token'),
            })
            return refreshToken;
        },
 }
});

So before calling viewAllOffers(), I need to check if access_token is present in $cookies or not if not thencall refresh_token service.

How do I achieve this generically?

user1608841
  • 2,455
  • 1
  • 27
  • 40
  • You can try with `request` interceptors in `$http` service, [here](https://docs.angularjs.org/api/ng/service/$http) is some documentation, scroll down to **Interceptor** part – MiTa Jun 25 '15 at 09:54

1 Answers1

2

Basically I need to check if access token present in $cookies or not before every service call in the application. If access token is not present, then Need to regenerate it..

.. How do I achieve this generically?

You can simply create an interceptor to check if the access_token exists in cookies before making any $http call. You would need to add use $injector to get mosServiceFactory instance inside of interceptor.

mPosServices.service('APIInterceptor', ['$injector', '$cookies', function($injector, $cookies) {
    var service = this;
    service.request = function(config) {
        if (!$cookies.get('access_token') && config.url.indexOf('myservice/oauth/token?grant_type=') === -1) {
            return $injector.get('mosServiceFactory').refresh_token().then(function(response) {
                var date = new Date();
                date.setTime(date.getTime() + (response.data.expiresIn * 1000));
                $cookies.remove('access_token');
                $cookies.put('access_token', response.data.value, {
                    expires: date
                });
                $cookies.put('refresh_token', response.data.refreshToken.value);
            }).then(function() {
                return config; // <-- token is refreshed, reissue original request
            });
        }
        return config;
    };

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

APIInterceptor will monitor all requests made with the $http service, perform pre-requisite operations (like regenerating access_token) and intercept any response errors.

You would need to push the interceptor to $httpProvider in your config function.

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

EDIT: Since the request to refresh_token is also making use of $http service, you would get a circular dependency error. This is because every time you find $cookies.get('access_token') empty, the interceptor will try to get a new token from mosServiceFactory.refresh_token() which again will bring interceptor into play. To avoid this, you need to make a check within APIInterceptor to let the request proceed if grant_type !='refresh_token'

nalinc
  • 7,375
  • 24
  • 33
  • I am doing exactly same thing as shown above in code , But I am getting error as **"Circular dependency found: $http <- mosServiceFactory <- APIInterceptor <- $http <- $templateRequest <- $compile"** Not sure what I am doing wrong here. – user1608841 Jun 25 '15 at 11:26
  • @Rahul: Yes I missed it. You were getting the circular dependency error because `APIInterceptor` calls `mosServiceFactory.refresh_token` whenever it doesnt find the access_token. since Interceptors act as a middleware in all request/response cycles it tries to call `refresh_token` even if the $http request is being made from refresh_token itself. Please check the updated answer. – nalinc Jun 26 '15 at 06:04
  • ohh yes..now I understand why I am getting this error, but does config object has grand_type property ? or we need to set this property for each $http call, so that It can be captured in interceptor? – user1608841 Jun 26 '15 at 06:22
  • You yourself are setting it in the `refresh_token()` request URL. `url: "myserviceurl/oauth/token?grant_type=refresh_token..` – nalinc Jun 26 '15 at 06:24
  • Ohh sorry , My bad... I tried ,but config.grant_type is not working, went through angular https://docs.angularjs.org/api/ng/service/$http docs, I found config object has params property, but its returning undefined. I am not able to check grant_type as url param – user1608841 Jun 26 '15 at 06:40
  • You should follow the right syntax. `$http.get(,)` – nalinc Jun 26 '15 at 06:45
  • `$http.get("myserviceurl/oauth/token",{'grant_type':'refresh_token','client_id':‌​'restapp','client_secret':'restapp','refresh_token':$cookies.get('refresh_token')‌​})` – nalinc Jun 26 '15 at 06:46
  • Where options is in json format. For http GET requests, it will be passed as query_string – nalinc Jun 26 '15 at 06:48
  • actually once I inject mosServiceFactory in my service above, i get circular dependency error. Even I tried manually injecting using $injector, but still getting same error. – user1608841 Jun 26 '15 at 06:59
  • 1
    @Rahul: Updated the code. See [this](http://stackoverflow.com/a/31066786/1379667) asnwer for details. – nalinc Jun 26 '15 at 07:11
  • @Rahul: Feel Free to upvote/accept if this helped in any way. That'll allow other people to rectify similar issues in future :) – nalinc Jun 26 '15 at 07:21