Reputation: 5945
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
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