42

I have an angular application that is hitting a node API. Our backend developer has implemented basic auth on the API, and I need to send an auth header in my request.

I've tracked down:

$http.defaults.headers.common['Authorization'] = 'Basic ' + login + ':' + password);

I've tried:

.config(['$http', function($http) {
       $http.defaults.headers.common['Authorization'] = 'Basic ' + login + ':' +    password);
}])

As well as appending it directly to the request:

$http({method: 'GET', url: url, headers: {'Authorization': 'Basic auth'}})})

But nothing works. How to solve this?

1
  • really strange ... you don't have other things in your config or are you behind a proxy something like that ? Commented Sep 18, 2013 at 18:23

8 Answers 8

33

You're mixing the use cases; instantiated services ($http) cannot be used in the config phase, while providers won't work in run blocks. From the module docs:

  • Configuration blocks - […] Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.
  • Run blocks - […] Only instances and constants can be injected into run blocks. This is to prevent further system configuration during application run time.

So use either of the following:

app.run(['$http', function($http) {
    $http.defaults.headers.common['Authorization'] = /* ... */;
}]);
app.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.headers.common['Authorization'] = /* ... */;
}])
Sign up to request clarification or add additional context in comments.

7 Comments

Why cannot we write $http.defaults.headers.common['Authorization'] = /* ... */; in controller level?
because its a configuration thing, and you're working on one concrete instance of that service.
Is there a particular reason for using ['Authorization'] versus just .Authorization ?
@DannyBullis - just a convention, AFAIK. perhaps that convention was made for convenience; more than often you'll have the HTTP headers as constants somewhere, so addressing the key by using a string allows you to use those constants as key references, e.g. $http.defaults.headers.common[HTTP_HEADER_KEY_AUTH].
@natureminded thanks, yeah I know that. I was just curious about the stylistic approach. Using square bracket notation allows for using arbitrary property values to define which property you are accessing, whereas dot notation targets only a specific, non-dynamically defined property. This convention is much more widely used in JavaScript than just in this specific instance, but I wasn't sure if there was some other specific reason for using square brackets here. I just needed clarification :) thanks for your help guys.
|
14

I have a service factory that has an angular request interceptor like so:

var module =  angular.module('MyAuthServices', ['ngResource']);

module
    .factory('MyAuth', function () {
    return {
        accessTokenId: null
    };
})    
.config(function ($httpProvider) {
    $httpProvider.interceptors.push('MyAuthRequestInterceptor');
})

.factory('MyAuthRequestInterceptor', [ '$q', '$location', 'MyAuth',
    function ($q, $location, MyAuth) {
        return {
            'request': function (config) {


                if (sessionStorage.getItem('accessToken')) {

                    console.log("token["+window.localStorage.getItem('accessToken')+"], config.headers: ", config.headers);
                    config.headers.authorization = sessionStorage.getItem('accessToken');
                }
                return config || $q.when(config);
            }
            ,
            responseError: function(rejection) {

                console.log("Found responseError: ", rejection);
                if (rejection.status == 401) {

                    console.log("Access denied (error 401), please login again");
                    //$location.nextAfterLogin = $location.path();
                    $location.path('/init/login');
                }
                return $q.reject(rejection);
            }
        }
    }]);

Then on logging in in my login controller I store the accesstoken using this line:

sessionStorage.setItem('currentUserId', $scope.loginResult.user.id);
sessionStorage.setItem('accessToken', $scope.loginResult.id);
sessionStorage.setItem('user', JSON.stringify($scope.loginResult.user));
sessionStorage.setItem('userRoles', JSON.stringify($scope.loginResult.roles));

This way I can assign the headers to the request on every request made after I log in. This is just the way I do it, and is totally up for criticism, but it appears to work very well.

Comments

13

You can use it in the controller:

.controller('Controller Name', ['$http', function($http) {
   $http.defaults.headers.common['Authorization'] = 'Basic ' + login + ':' + password;
}]);

5 Comments

It might work, but It should not be done in a controller
Should be done in the config phase, but it also needs to be done after a login so it's possible that you could set this in a logincontroller
Makes perfect sense for my case. If you are fetching data from different API's you want to configure it on particular part not for the whole web app. +1
@LouieAlmeda I think you are right. It shouldn't be done in a controller. But Sjoerd has a point too. You should be able to set it on login. That's why I put this stuff and other $http calls in factories. I think that separates the logic from what should happen in the controller from practical stuff like this.
@david.carm then set it on your login service, called from a controller. Unless you don't have that service and doing everything in the controller
6

In the angularjs documentation you can see some ways to set headers but I think this is what you are searching:

$http({
    method: 'POST',
    url: '/theUrl',
    headers: {
        'Authorization': 'Bearer ' + 'token'
         //or
         //'Authorization': 'Basic ' + 'token'
    },
    data: someData
}).then(function successCallback(response) {
    $log.log("OK")
}, function errorCallback(response) {
    if(response.status = 401){ // If you have set 401
        $log.log("ohohoh")
    }
});

I'm using this structure in my angularjs client with an ASP.NET 5 server and it works.

1 Comment

There is no reason to add JQuery to an Angular project just for Ajax auth headers.
4

In the $http doc you can see that you should set the default headers using $httpProvider:

.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.headers.common['Authorization'] = 'Basic auth';
}]);

Comments

2

WORKING EXAMPLE: I have learnt this from @MrZime - Thanks! and Read https://docs.angularjs.org/api/ng/service/$http#setting-http-headers

Latest v1.6.x of NGULARJS as of 2018 MARCH 2nd

        var req = {
            method: 'POST',
            url: 'https://api.losant.com/applications/43fdsf5dfa5fcfe832ree/data/last-value-query',
            headers: {
                'Authorization': 'Bearer ' + 'adsadsdsdYXBpVG9rZW4iLCJzrdfiaWF0IjoxNdfsereOiJZ2V0c3RfdLmlvInfdfeweweFQI-dfdffwewdf34ee0',
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            data: {
                "deviceIds": [
                    "a6fdgdfd5dfqaadsdd5",
                    "azcxd7d0ghghghghd832"
                ],
                "attribute": "humidity"
            }
        }




        $http(req).then(function successCallback(response) {

            $log.log("OK!")
             returnedData = response.data

        }, function errorCallback(response) {

            if (response.status = 401) { // If you have set 401

                $log.log("BAD 401")

            }
            else {

                $log.log("broken at last")

            }
        });

Add it to your.js file and include this your.js in your.html file and look at console panel in debug/F12 on chrome you should get OK status and "returnedData" is what you want in the end. Enjoy the data!

Comments

1

Try base64 encoding your user:password before you append it to "Basic", as in:

headers: {
  'Authorization': "Basic " + auth64EncodedUserColonPass
}

Comments

1

add below line in your aap.run method

$http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w';

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.