API Call with NodeJS signing with Oauth1 not working - node.js

I have a problem with my api call using NodeJS. I have no problem with postman, but when I run it with Node, server response is 401.
Here's the nodejs code:
var request = require("request");
var options = { method: 'GET',
url: 'https://api.cardmarket.com/ws/v2.0/output.json/products/find',
qs:
{ search: 'Salamangrande%25Loup%25Du%25Soleil',
idGame: '3',
idLanguage: '2' },
headers:
{ 'cache-control': 'no-cache',
Connection: 'keep-alive',
Cookie: 'PHPSESSID=m399v2el9635i3jq0e4did8f5k',
'Accept-Encoding': 'gzip, deflate',
Host: 'api.cardmarket.com',
'Postman-Token': '9b19a85d-8888-4f31-8d24-fe309a55bf76,4d8f4741-4b85-4d5e-85dc-8ac43ea5f56c',
'Cache-Control': 'no-cache',
Accept: '*/*',
'User-Agent': 'PostmanRuntime/7.19.0',
Authorization: 'OAuth realm="https%3A%2F%2Fapi.cardmarket.com%2Fws%2Fv2.0%2Foutput.json%2Fproducts%2Ffind",oauth_consumer_key="xxxxxxxxx",oauth_token="xxxxxxxxx",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1579186959",oauth_nonce="vWUKBoTTkle",oauth_version="1.0",oauth_signature="ZD2TwzLVHqOjLm3u%2BWv%2FsQ8mdfs%3D"' } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(response.statusCode);
});
So basically here's my (perfectly working) .
Any idea what's wrong with the syntax or how to properly implement the oauth signature in the headers ?

HTTP 401 error means "unauthorized".
I don't think OAuth authorization is meant to be passed through the headers.
It is supposed to be something like :
var request = require("request");
url='https://api.cardmarket.com/ws/v2.0/output.json/products/find';
oauth = {
consumer_key: CONSUMER_KEY,
consumer_secret: CONSUMER_SECRET,
token: AUTH_TOKEN,
token_secret: TOKEN_SECRET,
signature_method : 'RSA-SHA1',
};
qs = {
search: 'Salamangrande%25Loup%25Du%25Soleil',
idGame: '3',
idLanguage: '2'
};
request.get({url:url, oauth:oauth, qs:qs, json:true}, function (e, r, product) {
console.log(product)
})
Check the request docs for more explanation on how to deal with OAuth in request.
(I strongly suggest using Axios instead of request, but that's up to you)

Related

'An error occurred while trying to authenticate: Failed to validate signature.' While using `oauth-1.0a` and nodejs

I'm getting this odd error in nodejs when I try to send a post request with oauth-1.0a and node.js.
Request:
Headers:
Authorization: OAuth <...>
Accept: 'application/xml',
Content-Type: 'application/xml'
Body:
<account>
<firstName>${first}</firstName>
<lastName>${last}</lastName>
<email>${email}</email>
<urlRedirect>${redirecturl}</urlRedirect>
</account>`
Response:
401
An error occurred while trying to authenticate: Failed to validate signature.
Code:
require('dotenv').config()
const request = require('request')
const OAuth = require('oauth-1.0a')
const crypto = require('crypto')
var first = "real";
var last = "person";
var email = "real#person.com";
var redirecturl = "http://google.com"
const oauth = OAuth({
version: '1.0a',
consumer: {
key: process.env.CONSUMERKEY,
secret: process.env.CONSUMERSECRET,
},
signature_method: 'HMAC-SHA1',
hash_function(base_string, key) {
return crypto
.createHmac('sha1', key)
.update(base_string)
.digest('base64')
},
})
console.log(oauth)
const token = {
key: process.env.KEY,
secret: process.env.SECRET,
}
const request_data = {
url: `https://${process.env.CHURCHCODE}.fellowshiponeapi.com/v1/Accounts`,
method: 'POST',
data: `<account>
<firstName>${first}</firstName>
<lastName>${last}</lastName>
<email>${email}</email>
<urlRedirect>${redirecturl}</urlRedirect>
</account>`
}
const headers = Object.assign( oauth.toHeader(oauth.authorize(request_data, token)), {
Accept: 'application/xml',
'Content-Type': 'application/xml'
});
console.log(headers);
request(
{
url: request_data.url,
method: request_data.method,
headers: headers
},
function(error, response, body) {
console.log(response.statusCode)
console.log(response.statusMessage)
}
)
Why is this error occurring?
Edit: one of the more useful resources I used was this: https://oauth.net/core/1.0/#signing_process but I still can't figure this out.
Should also mention that this request does work, as in postman it successfully goes through.
You typically want to provide the token in a request using this header:
Authorization: Bearer <token>
Not
Authorization: OAuth <...>

Upload video to Cloudflare API

I am trying to upload some videos to Cloudflare Stream API. Here is official documentation and its example request using curl: https://developers.cloudflare.com/stream/uploading-videos/upload-video-file/
I am doing the request in Node.js
const uploadVideo = (video: Express.Multer.File): => {
const formData = new URLSearchParams();
formData.append('file', video);
let cloudflareResponse;
try {
cloudflareResponse = await axios.post(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/stream/copy`,
formData,
{
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'multipart/form-data',
//'Tus-Resumable': '1.0.0',
//'Upload-Length': '600',
//'Upload-Metadata': 'maxDurationSeconds 600'
}
}
);
} catch (e) {
console.log('Error while trying to upload video to Cloudflare API ', e);
}
}
The commented Headers I took from this article, in which the request is done in Django and I tried to replicate it https://medium.com/#berman82312/how-to-setup-cloudflare-stream-direct-creator-uploads-correctly-802c37cbfd0e
The error I am getting is a 400 and here is some of the response
config: {
url: 'https://api.cloudflare.com/client/v4/accounts/...../stream/copy',
method: 'post',
data: 'file=%5Bobject+Object%5D',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'multipart/form-data',
Authorization: 'Bearer .....',
'Tus-Resumable': '1.0.0',
'Upload-Length': '600',
'Upload-Metadata': 'maxDurationSeconds 600',
'User-Agent': 'axios/0.21.1',
'Content-Length': 24
},
data: { result: null, success: false, errors: [Array], messages: null }
I am sure something is wrong in the request and hope someone could help me spot the mistake or suggest some modifications that might help. I have been stuck with this problem for hours and on Postman I am also getting a 400 response when trying to send with form-data.

Connecting to api using basic auth Angular 8 Express js

I have set up an angular 8 app, that connects to an express API.
I'm running it locally, to test.
My front end app connects to http://localhost:4200/ and backend to http://localhost:3000/
I've set up an express route to connect to https://api.podbean.com/v1/podcasts?access_token=baee9cb65384a814e704adc626dc969bb019f84d
which works fine, returning all podcasts
But the debugToken endpoint never works via the express route, if I use https://api.podbean.com/v1/oauth/debugToken?access_token=baee9cb65384a814e704adc626dc969bb019f84d
Using postman with basic auth clientId = '7faf9a7ad38a01c7d900c' client_secret = 'a7a3825f02be39c57ff44' it works ok, but never when connecting via localhost
I'm using GET
It must be connecting because I get an object returned, although it's an error
In Angular:
debug() {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
Authorization: 'Basic ' + btoa('7faf9a7ad38a01c7d900c:a7a3825f02be39c57ff44')
})
};
console.log(httpOptions);
return this.http.get(`${this.configUrl}/debug/`, httpOptions);
}
Express:
router.get('/debug', function (req, res, next) {
var options = {
url: `https://api.podbean.com/v1/oauth/debugToken?access_token=${accessToken}`
}
request(options, function (err, response, body) {
console.log( req.headers);
if(err){
return res.status(500).json({
title: 'An error has occured',
error: err
})
}
res.json(JSON.parse(body));
next();
})
});
When I log the request headers in the express/node side
{host: 'localhost:3000',
connection: 'keep-alive',
pragma: 'no-cache',
'cache-control': 'no-cache',
'sec-fetch-mode': 'cors',
origin: 'http://localhost:4200',
authorization: 'Basic N2ZhZjlhN2FkMzhhMDFjN2Q5MDBjOmE3YTM4MjVmMDJiZTM5YzU3ZmY0NA==',
'content-type': 'application/json',
accept: 'application/json, text/plain, */*',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36',
dnt: '1',
'sec-fetch-site': 'same-site',
referer: 'http://localhost:4200/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-GB,en;q=0.9,en-US;q=0.8,it;q=0.7,es;q=0.6' }
Returned object:
{"error":"invalid_token","error_description":""}
Which tells me I'm connecting, just not correctly
Looks like you just confused endpoints. You are sending basic auth from Angular page to your Express endpoint,
which doesn't make much sense, because it's https://api.podbean.com who requires authorization, not your Express server.
Try adding basic auth credentials to the request which goes from your Express server to api.podbean.com
router.get('/debug', function (req, res, next) {
var options = {
url: `https://api.podbean.com/v1/oauth/debugToken?access_token=${accessToken}`,
headers: {
'Authorization': 'Basic ' + new Buffer("7faf9a7ad38a01c7d900c:a7a3825f02be39c57ff44").toString('base64')
}
}
request(options, function (err, response, body) {
...

Getting error 400 when calling an https request to apply a charge on Stripe API

I am using nodejs without any library/npm to make a charge on stripe using the test api key.
However I am always getting 400 status code response, and can't understand why, can someone give me an hint?
Here is my request details:
{ protocol: 'https:',
hostname: 'api.stripe.com',
method: 'POST',
path: 'v1/charges',
timeout: 5000,
headers:
{ 'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': 72 },
auth: 'sk_test_JOXtNqPjvpFgLXMiwuWWKZxu:' }
And here is my payload (using querystring.stringify):
amount=5000&currency=usd&description=Tiago_1541865841578&source=tok_amex
Thank you in advance for any help!
Here is the code, the method where I do the request it self:
helpers.sendRequest = function(protocol, port, hostname, method, path, timeoutSeconds, contentType, postData){
// Stringify the payload
var stringPayload = querystring.stringify(postData);
// Construct the request
var requestDetails = {
'protocol' : protocol+':',
'hostname' : hostname,
'method' : method,
'path' : path,
'port' : port,
'auth': ('Bearer ' + Buffer.from(config.stripe.secretApiKeyTest).toString('base64') + ":"),
'timeout' : timeoutSeconds * 1000,
'headers' :{
'Authorization': ('Bearer ' + Buffer.from(config.stripe.secretApiKeyTest).toString('base64') + ":"),
'teste':'ola',
"teste2":"ola2",
'Content-Type':contentType,
'Content-Length': Buffer.byteLength(stringPayload)
}
};
console.log("Request Details:")
console.log(requestDetails);
console.log("Payload:")
console.log(stringPayload);
// Instantiate the request object (using either the http or https module)
var _moduleToUse = protocol == 'http' ? http : https;
var req = _moduleToUse.request(requestDetails, function(res){
console.log(res.statusCode);
});
// Bind to the error event so it doesn't get thrown
req.on('error',function(e){
callback(err, e);
});
// Bind to the timeout event
req.on('timeout',function(){
callback(true, {'Error': 'The request took much time and got timeout.'})
});
// Add the payload
req.write(stringPayload);
// End the request
req.end();
};
And here is where I call the aux method to send the request:
var stripeRequestObject = {
amount: (totalPrice*100),
currency: 'usd',
description: userData.name+'_'+Date.now(),
source: stripeToken,
};
genericHelper.sendRequest('https',
443,
'api.stripe.com',
'POST',
'v1/charges',
5,
'application/x-www-form-urlencoded',
stripeRequestObject);
That is how I did it.
const requestDetails = {
protocol: 'https:',
hostname: 'api.stripe.com',
port: 443,
method: 'POST',
path: '/v1/charges',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(stringPayload),
Authorization: `Bearer ${config.stripe.testAPIkey.Secret}`
}
};
There is a typo in your code
'v1/charges'
should be
'/v1/charges'
In the auth you need to add Bearer before the token, that's how you send tokens to API. I tried to do the request on postman and it works, you can use axios or superagent to perform the request in you js file

Gzip decompression of http Response

Using request module, I am trying to fetch response from a web service which has following header in the API request:
accept-encoding : gzip
and correspondingly, following header in the response :
content-encoding : gzip
When I am trying to decompress the response(get the correct readable response) using zlib(referred here), I am unable to do so.
Code Snippet :
var options = {
url: url,
qs: params.qparams,
method: params.method,
json: params.body,
headers: {
'api_key': configkey,
'Content-Type': 'application/json',
'Accept-Encoding': 'gzip'
},
timeout: constants.request_timeout
};
request(options, function(err, response, body) {
var encoding = response.headers['content-encoding']
if (encoding && encoding.indexOf('gzip') >= 0) {
zlib.gunzip(body, function(err, dezipped) {
//ERROR : { [Error: incorrect header check] errno: -3, code: 'Z_DATA_ERROR' }
var json_string = dezipped.toString('utf-8');
var json = JSON.parse(json_string);
console.log('\nJSON ::\n',json);
});
} else {
console.log('\n\nRESPONSE IS NOT GZIPPED!');
}
}
I am getting an error here(as commented in the code), using zlib.
I could not figure out as where is it going wrong, tried with multiple npm modules like unzipResponse and compress-buffer and tried different approaches as well as suggested at various places for handling gzip.
If someone can help out in resolving this, I'll be really thankful.
I have got a solution as need to add one more key to the options object as :
var options = {
url: url,
qs: params.qparams,
method: params.method,
json: params.body,
headers: {
'api_key': configkey,
'Content-Type': 'application/json',
'Accept-Encoding': 'gzip'
},
timeout: constants.request_timeout,
encoding: null
};
If someone has a better approach to perform the decompression, please add-on.

Resources