I have a factory which returns token as
var accessToken = Restangular.all(url);
accessToken.one('token').get()
.then(function(res) {
deferred.resolve(res.data);
})
.catch(function(errRes) {
deferred.reject(errRes);
});
return deferred.promise;
In my header Interceptor, I need to get the token. Tried below code :
var accessToken;
$injector.get('tokenService').accessToken().then(function(res) {
accessToken = res.access_token;
}, function(e) {
// error
});
req.headers = _.extend({
'Authorization': 'Bearer ' + accessToken
}, req.headers);
Every time I get accessToken as undefined. There should be an easy way to achieve this.
Because you are forming req.headers outside accessToken()'s ajax call. Which tend to make your res.headers object with undefined access_token. Ideally you should wait until accessToken() ajax gets complete & set your res.headers code inside accessToken().then.
Factory
var accessToken = Restangular.all(url);
return accessToken.one('token').get()
.then(function(res) {
return res.data;
})
.catch(function(errRes) {
return errRes;
});
}
Interceptor
var accessToken;
$injector.get('tokenService').accessToken().then(function(res) {
accessToken = res.access_token;
req.headers = _.extend({
'Authorization': 'Bearer ' + accessToken
}, req.headers);
}, function(e) {
// error
});
Related
I'm learning nodejs and trying to make an API call. The API uses JWT to authenticate.
I created these functions to sign a token:
function token() {
const payload = {
iat: Math.floor(new Date() / 1000),
exp: Math.floor(new Date() / 1000) + 30,
sub: "api_key_jwt",
iss: "external",
jti: crypto.randomBytes(6).toString("hex")
};
return new Promise((resolve, reject) => {
jwt.sign(payload, privatekey, { algorithm: "RS256" }, function(
err,
token2
) {
if (err) reject(err);
else resolve(token2);
});
});
}
exports.genToken = async function() {
const header = {
"x-api-key": api
};
const data = {
kid: api,
jwt_token: await token()
};
async function authorization(req, res) {
try {
const auth = await rp({
url: authurl,
method: "POST",
headers: header,
body: data
});
res.send(auth.body);
} catch (error) {
res.send(404).send();
}
}
return {
"x-api-key": api,
Authorization: "Bearer " + authorization()
};
};
This works fine. Then I created a function to make the API call:
const token = require("./index").genToken;
const rp = require("request-promise");
exports.getOrderBook = function(res, error) {
const full_url = url + "order_book";
const auth = token();
rp({
url: full_url,
method: "GET",
headers: auth,
body: {
market: "btceur"
},
json: true
})
.then(function(response) {
res(response);
})
.catch(function(err) {
error(err);
});
};
And I call it using Express:
routes.get("/orderbook", async (req, res, next) => {
try {
const book = await orders.getOrderBook();
res.send(book);
} catch (error) {
next(error);
}
});
However, when I call my API, it shows an error in console:
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of
type string or Buffer. Received type object.
I guess the error is something with the token generation, because if I console.log(auth) in the getOrderBook function, it shows Promise { <pending> }, so probably an object is being passed as the jwt token.
Is it really the problem? I tried a lot of different solutions that I found on internet, however the concept of Async/Await is new to me, and I'm having some troubles to figure it out.
Thanks a lot in advance guys!
Since getToken is an anync function, the return is wrapped in a Promise as well so you would need another anync/await:
exports.getOrderBook = async function() {
let response;
try {
const full_url = url + "order_book";
const auth = await token();
response = await rp({
url: full_url,
method: "GET",
headers: auth,
body: {
market: "btceur"
},
json: true
});
} catch (e) {
// handle error
throw e
// or console.error(e)
}
return response;
};
In this line as well Authorization: "Bearer " + authorization(), authorization is returning a promise
const bearer = await authorization()
return {
"x-api-key": api,
Authorization: "Bearer " + bearer
};
For error handling wrap entire thing in try..catch block
exports.genToken = async function() {
try {
const header = {
"x-api-key": api
};
const data = {
kid: api,
jwt_token: await token()
};
async function authorization(req, res) {
let auth;
try {
auth = await rp({
url: authurl,
method: "POST",
headers: header,
body: data
});
// res object not available
// res.send(auth.body);
} catch (error) {
// res object not available, better throw error and handle in your middleware
// res.send(404).send();
}
return auth
}
const bearer = await authorization()
} catch (e) {
// handle error
}
return {
"x-api-key": api,
Authorization: "Bearer " + bearer
};
}
I am using the Axios library for my ajax requests so I created an instance of axios.
When I hit the endpoint /user/login, the success response will return me a token that I will use in the header for future calls as the API is secured.
The problem is when I do a console.log(authUser) the object is empty even though in the .then(), I am setting authUser.bearerToken.
Why is this happening? And what's the solution? Thanks. See code below.
var ax = axios.create({
baseURL: 'http://api.site.test',
timeout: 5000,
headers: {
'X-Api-Client-Secret': 'xxxxxxxxxxxxxxxx'
}
});
var authUser = {};
// log the user in
ax.post('/user/login', {
email: 'e#maiiiiiiiiil.com',
password: 'ThisIsACoolPassword123!'
})
.then(function (response) {
// set the bearer token
authUser.bearerToken = response.data.token;
ax.defaults.headers.common['Authorization'] = authUser.bearerToken;
})
.catch(function (error) {
console.log(error);
});
console.log(authUser);
It's because its async. The code that talks to /user/login takes some time but your code continues.
So the order is
Create base axios
Define authUser as empty object
Send a request to /user/login
Console.log authUser
Get the response from the post request
You can see it more clearly if you put 3 console logs.
var ax = axios.create({
baseURL: 'http://api.site.test',
timeout: 5000,
headers: {
'X-Api-Client-Secret': 'xxxxxxxxxxxxxxxx'
}
});
var authUser = {};
console.log('authUser is ' + authUser);
// log the user in
ax.post('/user/login', {
email: 'e#maiiiiiiiiil.com',
password: 'ThisIsACoolPassword123!'
})
.then(function (response) {
// set the bearer token
authUser.bearerToken = response.data.token;
ax.defaults.headers.common['Authorization'] = authUser.bearerToken;
console.log('2. authUser is ' + authUser);
})
.catch(function (error) {
console.log(error);
});
console.log('3. authUser is ' + authUser);
You will see it in the following order: 1, 3, 2 and not 1, 2, 3.
ax.post is asynchronous ( non blocking ) so it won't execute in the order you want it to execute i.e it can execute any time ( or concurrently ). you either have to use callbacks or async...await to handle this
function f() {
var ax = axios.create({
baseURL: 'http://api.site.test',
timeout: 5000,
headers: {
'X-Api-Client-Secret': 'xxxxxxxxxxxxxxxx'
}
});
var authUser = {};
var response;
; ( async () => {
// log the user in
try {
response = await ax.post('/user/login', {
email: 'e#maiiiiiiiiil.com',
password: 'ThisIsACoolPassword123!'
})
} catch(ex) {
response = ex;
} finally {
if ( Error[Symbol.hasInstance](response) )
return console.log(response);
authUser.bearerToken = response.data.token;
ax.defaults.headers.common['Authorization'] = authUser.bearerToken;
}
})();
console.log(authUser)
}
I'm trying to add the 'Authorization' header containing a token for future HTTP request. Retrieval of the token seems to be fine however when making a get request it fails with an Unauthorized error message. After checking the request headers Authorization header does not exist in the request block...
window.crUtil = /*window.crUtil ||*/ (function() {
// Angular Services
var $injector = angular.injector(['ng']);
var $http = $injector.get('$http');
// getting the CFF data
function get_data() {
getJWTAWS();
var url = '/AWS/getDATA/555';
console.log('AUTH header before call: ' + $http.defaults.headers.common.Authorization);
$http.get(url,httpHeader).then(function successCallback(response) {
var data = response.data;
var cff = initCff();
alert(data.itemId);
}, function errorCallback(response) {
initCff();
alert("Error while getting data ");
});
}
function getJWTAWS() {
var httpConfig = {
cache: true,
params: {}
};
$http.get('/AWS/token', httpConfig).then(
function(response) {
if (response.data.accessToken) {
// add jwt token to auth header for all requests made by the $http service
$http.defaults.headers.common.Authorization = response.data.tokenType + ' ' + response.data.accessToken;
}
},
function(error) {
alert('jwt token could not be retrieved.');
}
);
}
})();
var result = util.get_data();
console.log ('called search function ' + result);
Function getToken() returns a value but as I'm new on that topic I'm not quite sure if the way I added the token to the headers is proper.
Could you please advise on the proper way to include the headers in the request. I also tried to add it to the get request like
$http.get(URL,httpHeaders)...
but it also didn't work.
I'm not sure I understand your problem completely as you did not provide what you call
httpConfig
If you're struggling to declare the headers, try making the get request like this:
$http({
method: 'GET',
url: YOUR_URL,
headers: {
'Content-Type': 'application/json',
'Authorization': AUTH_STRING_HERE
}
}).then(function (response) { ... });
You can add any headers you like in the headers object there.
Try adding this in your config block and set the token in your rootscope
$httpProvider.interceptors.push({
request: function (config) {
config.headers.Authorization = $rootScope.token;
return config;
}
})
I have read several examples on the web and issues here on SO but I'm still missing something.
I have a service to fetch order data from my API. I want to resolve the promise inside the service. The console.log inside the service logs the correct data.
However, in my controller i get "TypeError: Cannot read property 'then' of undefined"
I thought the controller function would wait for the data to be resolved?
Service
angular.module('app')
.factory('orderService', function($http) {
// DECLARATIONS
var baseUrl = 'http://api.example.com/';
var method = 'GET';
var orderData = null;
return {
getOrderData: getOrderData
};
// IMPLEMENTATIONS
function getOrderData(ordernumber) {
// order data does not yet exist in service
if(!orderData) {
dataPromise = $http({
url: baseUrl + 'order/' + ordernumber,
method: method,
withCredentials: true,
headers: {
'Content-Type': 'application/json'
}
// success
}).then(function(response) {
orderData = response.data;
console.log('Received data: ' + JSON.stringify(response.data));
return orderData;
},
// faliure
function(error) {
console.log("The request failed: " + error);
});
// order data exist in service
} else {
console.log('Data present in service: ' + orderData);
return orderData;
}
} // end: getOrderData function
}); // end: customerService
Controller
app.controller('orderController', function($scope, $stateParams, orderService) {
$scope.ordernumber = $stateParams.order;
orderService.getOrderData($scope.ordernumber)
// success
.then(function(response) {
$scope.order = response;
console.log('Controller response: ' + response);
},
// faliure
function(error) {
console.log("The request failed: " + error);
});
});
your function getOrderData doesn return a promise
function getOrderData(ordernumber) {
var deferred = $q.defer();
// order data does not yet exist in service
if(!orderData) {
dataPromise = $http({
url: baseUrl + 'order/' + ordernumber,
method: method,
withCredentials: true,
headers: {
'Content-Type': 'application/json'
}
// success
}).then(function(response) {
orderData = response.data;
console.log('Received data: ' +
JSON.stringify(response.data));
deferred.resolve(orderData);
},
// faliure
function(error) {
deferred.reject(error);
console.log("The request failed: " + error);
});
// order data exist in service
} else {
console.log('Data present in service: ' + orderData);
deferred.resolve(orderData);
}
else {
deferred.reject('Not set!');
}
return deferred.promise;
} // end: getOrderData function
I have a problem and don´t know how to solve it...
I have to authenticate a user in my IonicApp through a token based authentication. So i have to store the token inside the app, which shouldn´t be a problem...
The Problem is: How can i get the token?
Here´s my code:
// Alle Aufrufe an die REST-Api werden hier durchgeführt
var httpCall = {
async : function(method, url, header, params, data) {
// if (url != 'login') {
// header['X-Auth-Token'] = userTokenFactory.getUserToken();
// }
//console.log(header['X-Auth-Token']);
var ipurl = "IPURL";
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http({
method : method,
url : ipurl + url,
//headers : header,
params : params,
data : data,
config : {
timeout : 5000
}
}).then(function successCallback(response) {
//console.log("data:" + response.data);
//console.log("header:" + response.headers);
console.log("token:" + response.headers['X-AUTH-TOKEN']);
//console.log(response.data.token);
console.log("token" + repsonse.token);
// TRY TO READ THE X_AUTH_TOKEN HERE !!!!!!!!!!!!
return response;
}, function errorCallback(response) {
return response;
});
// Return the promise to the controller
return promise;
}
};
return httpCall;
});
And here´s a picture of the Response from the Server (from Firefox). As you can see, the X-Auth-Token is there...
here´s the x-auth-token
Thanks for the help!!
There are lot of articles are available over handling authentication in AngularJS. This article is the one perfect suitable in your case.
So you can get token from your request as,
}).then(function successCallback(response) {
console.log("data:" + response.data);
$window.sessionStorage.token = response.data.token;
return response;
}, function errorCallback(response) {
return response;
});
Now we have the token saved in sessionStorage. This token can be sent back with each request by at least three ways
1. Set header in each request:
`$http({method: 'GET', url: url, headers: {
'Authorization': 'Bearer ' + $window.sessionStorage.token}
});`
2. Setting defaults headers
`$http.defaults.headers.common['X-Auth-Token'] = 'Bearer ' + $window.sessionStorage.token;`
3. Write Interceptor:
Interceptors give ability to intercept requests before they are
handed to the server and responses before they are handed over to the
application code that initiated these requests
myApp.factory('authInterceptor', function ($rootScope, $q, $window) {
return {
request: function (config) {
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
}
return config;
},
response: function (response) {
if (response.status === 401) {
// handle the case where the user is not authenticated
}
return response || $q.when(response);
}
};
});
myApp.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
});
Refer AngularJS $http guide for detailed explanation.
As you are getting response.data null and image demonstrates that headers are being returned, I would suggest you to check if you are getting data with
response.headers(),
if then try with response.headers()["X_AUTH_TOKEN"].