1

I am using the Django REST token authentication for my API.

I posted my credentials to obtain token endpoint. However when I try to set the header in a correct way it keeps responding with a http 401 error. I tried it using curl -X GET http://127.0.0.1:8000/events/ -H 'Authorization: Token 4d92d36768ca5d555b59cf68899eceab39c23704 ' and that does work! This is my code:

app.controller('HomeController', ['$scope','$http', function($scope,$http) {
    $scope.username = '';
    $scope.password = '';
    $scope.submitLogin = function () {
        var credentials = {
            username : $scope.username,
            password : $scope.password,
        };

        var req = $http.post('http://127.0.0.1:8000/api-token-auth/', credentials);
        req.success(function(data, status, headers, config) {
            $scope.token = data.token;
            var str1 = 'Token ';
            $scope.tokenheader = str1.concat($scope.token);
            $http.defaults.headers.common.Authorization = $scope.tokenheader;
        });
        req.error(function(data, status, headers, config) {
            alert( "failure message: " + JSON.stringify({data: data}));
        });
    };
    $scope.getEvents = function () {
        var req = {
            method: 'GET',
            url: 'http://127.0.0.1:8000/events/',
        }
        $http(req).then( 
           function() {
                       console.log('succes')
           }, 
           function(){
                       console.log('fail') 
        });
    };
}]);

And the error message in chrome dev tools:

XMLHttpRequest cannot load http://127.0.0.1:8000/events/. 
Response for preflight has invalid HTTP status code 401

How do I get rid of this 401 error?

Edit: I just found out the fault lies in the fact that I did not have CORS installed on my API. I was using a CORS plugin in chrome that worked for the authentication part of my api but not for my events url!

2
  • Is the success callback really called on submitLogin ? Legacy promise methods success and error are dreprecated. Commented Nov 10, 2015 at 10:57
  • Yeah, they're working. I get the token and the http response code from my api is 200 Commented Nov 10, 2015 at 12:59

2 Answers 2

1

Did you check that the token is actually added to your request?

You can do this for example using the Chrome developers tools.

Personally I prefer to use the $httpprovider.interceptor as described in:

angularjs $httpProvider interceptor documentation

This ensures that the tokens are always present on any call.

If you are accessing more than one API, you should consider adding something like:

           $httpProvider.interceptors.push(['$q', '$location', '$log', 'loginService', 'restHelperService',
            function ($q, $location, $log, loginService, restHelperService) {
                return {
                    request: function (config) {
                        // check if the request comes with an url
                        if (config.url) {
                            // check that the call is to the REST api, if yes add token
                            if (restHelperService.isRestCall(config.url)) {
                                // add auth header or revert to login
                                if (loginService.userIsLoggedIn()) {
                                    config.headers = config.headers || {};
                                    config.headers.Authorization = 'Token ' + loginService.getToken().token;
                                } else {
                                    $location.path('/login');
                                }
                            }
                        }
                        return config;
                    },
                    responseError: function (response) {
                        if (response.status === 401 || response.status === 403) {
                            // clear auth token if the REST call failed with the current token
                            if (response.config && response.config.url && restHelperService.isRestCall(response.config.url)) {
                                $log.debug(" restCall failed due to bad credentials, resetting credentials");
                                loginService.resetCredentials();
                                $location.path('/login');
                            }
                        }
                        return $q.reject(response);
                    }
                };
            }]);
    }])

This avoid issues that will arise when you start adding the token to API calls that don't expect them. Also the code ensures that a user will be automatically redirected to the login page if the credentials are not valid.

The example, I'm using two additional services. A loginService that manages the tokens and a restHelperService that manages the urls of the REST framework.

I would recommend doing the same as else it will be hard to access the credentials from outside your controller.

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

2 Comments

PS once you move this onto a server, don't forget: django-rest-framework.org/api-guide/authentication/…
Thanks for the tip, I will look into it!
1

You need to add Token to the headers:

get($http, "/some_url", {headers: {"Authorization": "Token " + $your_token}}
    ....
    ....
);

Response code 401 means Unauthorized. If you are using Token based authentication then in case of fail it would be 403, Forbidden. So my guess would be that it's username/password who is messing with it. In your curl example you are not using them.

3 Comments

I already did that: var str1 = 'Token '; $scope.tokenheader = str1.concat($scope.token);
@icam0, But why are you using username and password then? I updated my answer.
That's because in my html I have 2 buttons. One that I connected to the submitlogin() function and the other one that I connected to the getEvent() function. I first requested the token with another curl command: curl -X POST http://127.0.0.1:8000/auth/login/ --data ‘username=icam0&password=password123’

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.