Zbynek
Zbynek

Reputation: 5945

Express JS app does not recognize authorization token send by Angular

I am working on api, which runs as Express JS app, and I am using Angular JS to send requests to that api.

The api requires authorization send in header and I am struggling to do that in angular.

My Express JS code:

app.all('*', function(req, res, next) {
// add details of what is allowed in HTTP request headers to the response headers
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Max-Age', '86400');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
// the next() function continues execution and will move onto the requested URL/URI
next();
});

app.use(function(req, res, next) {

var header=req.headers['authorization']||'',        // get the header
    token=header.split(/\s+/).pop()||'',            // and the encoded auth token
    auth=new Buffer(token, 'base64').toString(),    // convert from base64
    parts=auth.split(/:/),                          // split on colon
    username=parts[0],
    password=parts[1];

r(header);
r(token);
r(auth);
r(username);
r(password);

if(username=='usr' && password=='pwd'){
    next();
}else{

    res.set('WWW-Authenticate', 'Basic realm="Birds.cz login"');
    res.status(401).send({error:'auth'});
  }
}

When I use curl to send this: curl --user usr:pwd http://127.0.0.1:8000/v1/login, the console prints:

Basic dXNyOnB3ZA==
dXNyOnB3ZA==
usr:pwd
usr
pwd

which is correnct.

My angular service looks like this:

function testLogin() {
  $http({
     method  :'GET',
     url:'http://127.0.0.1:8000/v1/login',
        }).success(function(data, status, headers, config) {
            alert(data);
        }).error(function(data, status, headers, config) {
            alert('error');
        }).catch(function(error){
            alert('catch' + JSON.stringify(error));
        });

}

and in config of the whole angular app I have:

.config(function($stateProvider, $urlRouterProvider, $httpProvider) {

//Enable cross domain calls
$httpProvider.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';

// insert authorization header
var string = 'usr:pwd';
var encodedString = btoa(string);
$httpProvider.defaults.headers.common['Authorization'] = 'Basic ' + encodedString;

...
}

When I make request from Angular, the node js console prints five empty lines, therefore the Authorization header was not recognized at all.

Any ideas what is the problem?

EDIT When I use Authorization in http request header, the server returns error 0, but when I omit it, it returns error 401, as it should. It seems to me, that providing Authorization header breaks the code on server side before it sends the 401 error code.

EDIT 2 When I log the request header in node js app, it does not show token Authorization at all

{ host: '127.0.0.1:8000',
'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0',
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'cs,en-US;q=0.7,en;q=0.3',
'accept-encoding': 'gzip, deflate',
origin: 'http://localhost',
'access-control-request-method': 'GET',
'access-control-request-headers': 'authorization',
connection: 'keep-alive' }

EDIT 3 here is header of request, captured in firebug

Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language cs,en-US;q=0.7,en;q=0.3
Access-Control-Request-He...    authorization
Access-Control-Request-Me...    GET
Connection  keep-alive
Host    127.0.0.1:8000
Origin  http://localhost
User-Agent  Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0

Upvotes: 0

Views: 2093

Answers (1)

Nesh
Nesh

Reputation: 2541

Allow requests to come from different domains, add this code at server side to tackle CORS related error -

var resolveCrossDomain = function(req, res,next) {

    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
    res.header("Access-Control-Allow-Credentials", true);

    if ('OPTIONS' == req.method) {
        res.send(200);
    }
    else {
        next();
    }
}; 
    app.use(resolveCrossDomain);

Upvotes: 3

Related Questions