3

I successfully managed to use interceptors (AngularJs ) in my Ionic application. Previous post .

While it is working perfectly well in the browser using "ionic serve".

There is no content loaded in the header title and content block ( "ion-content" ) using "ionic run android" (either emulating on genymotion or on my own phone). See screenshot below.

no content / white screen using interceptors

I'm pretty sure it comes from the interceptors i'm using, because before that, the app was working on any platforms. Also, as soon as i remove the interceptors it is working again. Here the code.

Note that i'm checking which url is called so i don't go into a circular dependency or checking useless url, only the calls to my api go through.

app.config(function($httpProvider){

    $httpProvider.interceptors.push(['$location', '$injector', '$q', function($location, $injector, $q){

        return {

            'request' : function(config){

                // intercept request

                // carefull includes might not work while emulating
                // use instead indexOf for that case
                if(!config.url.includes('/oauth/v2/token') && config.url.includes('/api')){

                    // inject the service manually
                    var OauthService = $injector.get('OauthService');

                    var access_token = OauthService.token();
                    config.url = config.url+'?access_token='+access_token.key;

                }

                return config;
            }

        }

    }]);

});

Any ideas what could give this error? (By the way console is showing no errors on browser).

UPDATE :

OauthService.js :

app.factory('OauthService', function($http, $localStorage) {

return {
    token : function(){

        // Store actual token
        access_token = $localStorage.getObject('access_token');
        // Store actual identity
        identity_token = $localStorage.getObject('identity_token');

        // IF no user logged
        if(isObjectEmpty(identity_token)){

            // IF access_token does NOT exist OR will expires soon
            if( isObjectEmpty(access_token) || Date.now() > (access_token.expires_at - (600*1000)) ){

                // Create an anonymous access_token
                return $http
                    .get(domain+'/oauth/v2/token?client_id='+public_id+'&client_secret='+secret+'&grant_type=client_credentials')
                    .then(function (response) {

                        $localStorage.setObject('access_token', {
                            key: response.data.access_token,
                            type: 'anonymous',
                            expires_at: Date.now()+(response.data.expires_in*1000)
                        });

                        return response.data.access_token;

                    });
            }

        }
        // IF user is logged
        else{

            // IF access_token does NOT exist OR will expires soon OR is anonymous
            if( isObjectEmpty(access_token) || Date.now() > (access_token.expires_at - (600*1000)) || access_token.type == 'anonymous' ){
                // Create an access_token with an identity
                return $http
                    .get(domain+'/oauth/v2/token?client_id='+public_id+'&client_secret='+secret+'&api_key='+identity_token+'&grant_type=http://oauth2.dev/grants/api_key')
                    .then(function (response) {

                        $localStorage.setObject('access_token', {
                            key: response.data.access_token,
                            type: 'identity',
                            expires_at: Date.now()+(response.data.expires_in*1000)
                        });

                        return response.data.access_token;

                    });
            }

        }

        return access_token.key;

    }
};

})
Community
  • 1
  • 1
Brieuc
  • 3,994
  • 9
  • 37
  • 70
  • Are you returning a promise in `OauthService.token()` ? – LeftyX Jun 03 '15 at 07:56
  • I don't think so, i'm kinda new with the concept of promises/deferred. I updated the post with the OauthService source code. – Brieuc Jun 03 '15 at 08:13
  • But while launching for the first time it is not supposed to call the api yet (Login page). So we are not going through the condition yet and it is already displaying a white screen. I wonder if the interceptors is not messing up with my routes. – Brieuc Jun 03 '15 at 08:27
  • 1
    I guess it is. Check my updated answer. There's a rough idea how an interceptor dealing with bearer token should work. – LeftyX Jun 03 '15 at 08:36

1 Answers1

3

Did you install cordova whitelist plugin ?

cordova plugin add cordova-plugin-whitelist

or if you want to save the reference to your config.xml file:

cordova plugin add cordova-plugin-whitelist --save

If you don't have that your device won't be able to access external resources.

You can find more info here.

UPDATE:

I've checked your previous answer.
The idea of the interceptor is to intercept calls to an external service insert some action in the pipeline.

I would change your interceptor:

$httpProvider.interceptors.push(['$location', '$injector', '$q', '$localStorage', function($location, $injector, $q, $localStorage){

    return {

        'request' : function(config) {
            config.headers = config.headers || {};

            access_token = $localStorage.getObject('access_token');

            if (access_token) {
                config.headers.Authorization = 'Bearer ' + access_token;
            }
        }

        'response' : function(response){

            if (response.status === 401) {
                logger.debug("Response 401");
            }
            return response || $q.when(response);
        }

        'responseError' : function(rejection){

            if (rejection.status === 401) {
                var OauthService = $injector.get('OauthService');
                var access_token = OauthService.token();

                if (access_token === null)
                {
                    return $q.reject(rejection);
                }

                // Append your access token to the previous request and re-submits.
                rejection.config.headers['Authorization'] = 'Bearer ' + access_token;
                return $injector.get('$http')(rejection.config);
            }

            // This is necessary to make a `responseError` interceptor a no-op. 
            return $q.reject(rejection);
        }
    }
}]);

If you look at the interceptor above it manages all the requests to an external resource (REST api) and appends a bearer token to the authorization header if needed.

The response does not do much as it is only there for logging purposes.

responseError is the place where you should intercept and check if your token as expired, fetch a new one and resubmit the request.

We check if the user is not authorized to the request:

if (rejection.status === 401) { ... }

If not we request a new access token. I guess your OauthService does that. If we have a new access token:

var access_token = OauthService.token();

we can, again, append the access token to the request header:

rejection.config.headers['Authorization'] = 'Bearer ' + access_token;

and resubmit the previous request:

return $injector.get('$http')(rejection.config);

If you want to find out more about interceptors you can read these blogs.

Thomas Bormans
  • 5,156
  • 6
  • 34
  • 51
LeftyX
  • 35,328
  • 21
  • 132
  • 193
  • Yes i'm already using it. I can access external resources without the interceptors. – Brieuc Jun 03 '15 at 07:40
  • The responseError allowed me to find one of the error from the previous code. includes is not recognized while emulating so i replaced it with indexOf and it is working. Anyway i'll keep digging, your solution is a little bit more complex so i need a little bit more time to implement it. I'm not sure how to use the headers since i call my api with access token in the url, not in the header. – Brieuc Jun 03 '15 at 09:39
  • And the rejection.status also did a part of the job. Thank you! – Brieuc Jun 03 '15 at 09:44
  • 1
    Glad I've helped. I've included some links in my answer. You can find lot of useful information about interceptor and how they work. Cheers. – LeftyX Jun 03 '15 at 09:46