0

I'm building my (first) angular app that will have tokens inserted into headers (the content shown is for the most part taken from here)

angular.module('myApp')

.factory('sessionInjector', ['SessionService', function(SessionService) {  
   var sessionInjector = {
        request: function(config) {
            config.headers['x-session-token'] = SessionService.getToken();
            return config;
        }
    };
    return sessionInjector;
}])

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

The trouble I'm having is with SessionService - how can I initialize this with call to the server?

For example, this didn't work:

.factory('SessionService', ['$injector', function($injector){
    var token = "";

    return {
        getToken: function () {
            var http = $injector.get('$http');
            if (token === "") {
                http.get('http://localhost/api/auth/getToken').success(function (ret) {
                    token = ret;
                });
            }
            return token; 
            //I can see a $q/deferred/promise should be used somehow here... 
            //but I'm not sure it solves the problem I'm having...
        }
    }
}]);

because it just overloads my cpu to 100%...

Since it's my first angular app, I'm sure I'm missing something, but... what?

EDIT:
Another take on the matter... still doesn't work though... (again, uses up cpu, probably infinite loop)

  .factory('sessionData', function () {
    var currentToken = '[uninitialized-token]';

    return {
        getToken: function () {
            return currentToken;
        },
        setToken: function (token) {
            currentToken = token;
        }
    }
})

.factory('sessionInjector', ['sessionData', '$injector', '$q', function (sessionData, $injector, $q) {
    var sessionInjector = {
        request: function (config) {
            var deferred = $q.defer();
            var http = $injector.get('$http');
            http.get('http://localhost/api/auth/getToken').success(function (ret) {
                sessionData.setToken(ret);
                console.log("successfully authenticated with token " + sessionData.getToken());
                config.headers['x-header-sessionID'] = sessionData.getToken();
                deferred.resolve(config);
            })
            .error(function(){
                console.log("failed to authenticate");
                deferred.resolve(config);
            });

            return deferred.promise;
        }
    };
    return sessionInjector;
}])

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

.run(['$http', 'sessionData', function ($http, configs, sessionData) {
    $http.get('http://localhost/api/auth/testMethod').then(function (ret) {
        //do something...
    });
}])

2 Answers 2

1

Check whether this modified code fragment will solve your issues.

.factory('SessionService', ['$http', '$q', function($http, $q) {
    var token = null;
    var sessionService = {};
    var differred = $q.defer();

    sessionService.readToken = function() {
        return $http.get('http://localhost/api/auth/getToken')
            .success(function (res) {
                console.log('Auth Success and token received: ' + JSON.stringify(res.data));

                // Extract the token details from the received JSON object
                token = res.data;
                differred.resolve(res);
            }, function (res) {
                console.log('Error occurred : ' + JSON.stringify(res));
                differred.reject(res);
            }
        )
    };

    sessionService.getToken = function() {
        return token;
    };

    sessionService.isAnonymous = function() {
        if (token)
            return true;
        else
            return false;
    };

    return sessionService;
}])


.factory('sessionInjector', ['SessionService', function(SessionService) {
    var sessionInjector = {
        request: function(config) {
            if (!sessionService.isAnonymous) {
                config.headers['x-session-token'] = SessionService.getToken();
                return config;
            }
        }
    };
    return sessionInjector;
}])

.config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push('sessionInjector');
}])
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the reply - but it doesn't work. The $http you're using isn't injected. And even if it was it would create circular reference and wouldn't work. That's why I had to get the $http from $injector in time of the request for token (inside a function, under it's context at runtime when requested)...
There was a typo in the Session service declaration which corrected. Moreover, first you need to call the Session.readToken() method inside your controller to read it. Afterwards, if token available all consecutive requests will be dispatched with the token as a HTTP header parameter. This is working and tested. No circular references were observed, in the way I defined it.
This is the circular error I'm getting when I used your code: Uncaught Error: [$injector:cdep] Circular dependency found: $http <- SessionService <- sessionInjector <- $http <- $templateRequest <- $compile (AngularJS v1.4.3)
Could you prepare a Plunker for this.
plnkr.co/edit/vqTB0q?p=preview , I don't see a way to view the javascript console ... when you put code locally, you'd get the errors in the console...
0

Answer was actually pretty straight forward - if the targeted URL is for login, then don't inject anything (look for the comment the fix):

.factory('sessionData', function () {
    var currentToken = '[uninitialized-token]';

    return {
        getToken: function () {
            return currentToken;
        },
        setToken: function (token) {
            currentToken = token;
        }
    }
})

.factory('sessionInjector', ['sessionData', '$injector', '$q', function (sessionData, $injector, $q) {
    var sessionInjector = {
        request: function (config) {

            //The fix:
            if(config.url === 'http://localhost/api/auth/getToken')
                return config;

            var deferred = $q.defer();
            var http = $injector.get('$http');
            http.get('http://localhost/api/auth/getToken').success(function (ret) {
                sessionData.setToken(ret);
                console.log("successfully authenticated with token " + sessionData.getToken());
                config.headers['x-header-sessionID'] = sessionData.getToken();
                deferred.resolve(config);
            })
            .error(function(){
                console.log("failed to authenticate");
                deferred.resolve(config);
            });

            return deferred.promise;
        }
    };
    return sessionInjector;
}])

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

.run(['$http', 'sessionData', function ($http, configs, sessionData) {
    $http.get('http://localhost/api/auth/testMethod').then(function (ret) {
        //do something...
    });
}])

Comments

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.