Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angularjs - Authorization header not added in Safari

I'm currently building a webapp using Django + Django Rest Framework (DRF) in the back and Angularjs to construct the UI.

All requests are authenticated using the basic token authentication that is build into DRF. I implemented a basic interceptor in Angular to add the token, which is stored in session storage after login, to each request. This works fine in Google Chrome (I can see that the Authorization header is actually added to each request using the inspector) and Firefox. However in Safari the header is not added to some requests.

First of all, this is the interceptor I use:

app.factory('authInterceptor', ['$rootScope', '$q', '$window', function($rootScope, $q, $window){
    return {
        // This method adds the authentication token to each requests' header
        request: function(config){
            config.headers = config.headers || {};

            // add authentication token in header
            try {
                var token = $window.sessionStorage.token;
            } catch(err){
                token = undefined;
            }
            if(token !== undefined){
                config.headers.Authorization = 'Token ' + token;
            }
            return config;
        },
        response: function(response){
            if(response.status === 401){
                // user not authenticated
            }
            return response || $q.when(response);
        }
    };
}]);

One of the specific resources that gives me a headache in Safari is:

app.factory('Coach', ['$resource', '$rootScope',
    function($resource, $rootScope){
        return $resource(
            $rootScope.api_url + 'api/coaches/:coachId/?format=json',
            {
                coachId: '@id'
            }
            ,
            {
                getByUserId: {method:'GET', url: $rootScope.api_url + 'api/coaches', isArray:false},
                update: {method:'PUT'}
            }
        );
}]);

If have tried adding withCredentials to the getByUserId method but no luck.

My interceptor is properly pushed to the $httpService. I have verified that the token was available in Safari in the sessionStorage. I have printed the token to the console from the interceptor. Can't get my head around this issue.

Anyone?

like image 661
Bart Avatar asked Nov 29 '22 11:11

Bart


1 Answers

Finally stumbled upon the solution to this annoying problem. It turned out that it was actually related to how Angularjs removes trailing slashes in url's and how Django needs those slashes to perform its magic.

Because the trailing slash in Angular was removed, the server responded with a 301 (permanently moved) response. The Django Rest Framework then redirected the request to the correct url (including trailing slashed). However, for some reason in both IE and Safari, the authentication tokens were not passed into this second request. And there's your problem.

Hope this is of any help.

like image 167
Bart Avatar answered Dec 04 '22 10:12

Bart