Using AXIOS to POST to external server API to retrieve SSOID - api

In short: Here is some Python code posting to Betfair API. I would like to use Axios to do the same thing.
resp = requests.post('https://identitysso-cert.betfair.com/api/certlogin',
data=payload, cert=('TestApp.crt', 'client-2048.key'), headers=headers)
I'm reading through AXIOS docs, and am curious how to apply the cert=('TestApp.crt', 'cient-2048.key') field.
In detail: Currently, I have this:
axios({
method: "POST",
headers: headers,
url: "https://identitysso-cert.betfair.com/api/certlogin",
data: payload,
});
Would I use the form-data library replacing cert=('TestApp.crt', 'cient-2048.key') with form<FormData>
const FormData = require("form-data");
const form = new FormData();
form.append("my_field", "my value");
form.append("my_buffer", new Buffer(10));
form.append("my_file", fs.createReadStream("/foo/bar.jpg"));
axios.post("https://example.com", form, { headers: form.getHeaders() });
EDIT:
Scrapped the FormData route, and am using HTTPS for node js.
I add this along with the options I provide to Axios.
const httpsAgent = new https.Agent({
cert: fs.readFileSync("certificat.crt"),
ca: fs.readFileSync("key.pem"),
});
I in turn get this error:
Error: "Error: SSL Error: SELF_SIGNED_CERT_IN_CHAIN"

Digging a little deeper,
The error SELF_SIGNED_CERT_IN_CHAIN means that you cannot use self-signed certificates.
I ended up using Python to accomplish what I needed.

Related

CORS header ‘Access-Control-Allow-Origin’ missing on response in addon but not on request

I am creating a Firefox extension which posts some data to a database.
I made all parts in a modular fashion and am now combining everything piece by piece.
As such I know that my code to POST data to the database works.
Now here is the part that stumps me :
When I then add this code to my firefox extension
I get the following error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3003/timed_shot_create. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 400.
Now ofcourse CORS was nothing new and to be expected when dealing with Cross Origin Resource Sharing, it is even in the name.
But the reason why I am here is because this pertains only to the response of the POST request. The request itself is fine and allowed with the following piece of config in the server:
app.use(
cors({
//todo change to proper origin when live
origin: "moz-extension://d07f1e99-96a0-4934-8ff4-1ce222c06d0d",
method: ["GET", "POST"],
})
);
Which was later changed to:
app.use(
cors({
origin: "*",
method: ["GET", "POST"],
})
);
And then simplified even more to:
app.use(cors())
This is in Nodejs btw using cors middleware.
But none of this seems to work when it is used inside a firefox extension, as a local client page works as intended but as soon as I add this to a firefox extension I get a CORS error specifically pertaining to the reponse message.
The client side post (in the background script of the extension) is:
async function postTimedShot(post_options) {
const response = await fetch(post_endpoint, post_options);
//console.log(response);
const json_response = await response.json();
console.log(json_response);
}
let post_options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(response_data),
};
postTimedShot(post_options);
And the api looks like this:
app.post("/timed_shot_create", (req, res) => {
console.log("Received POST request");
const data = req.body;
console.log(data);
const timeStamp = data.time_stamp;
//TODO add screenshot and Description text maybe??
//const lastName = data.last_name
const queryString =
"INSERT INTO " + timed_shots_database + " (time_stamp) VALUES (?)";
getConnection().query(queryString, [timeStamp], (err, results, fields) => {
if (err) {
console.log("Failed to insert new user: " + err);
res.sendStatus(500);
return;
}
//Todo change this message when adding more data in body
//res.header("Access-Control-Allow-Origin", "moz-extension://d07f1e99-96a0-4934-8ff4-1ce222c06d0d");
res.json({
status: "Success!!!",
time_stamp: timeStamp,
});
console.log("Inserted a new user with id: ", results.insertId);
});
});
Furthermore, this extension is only for personal use and will work with a local server under my complete control so complications due to security or cloud usage that people want to mention are appreciated but not necessary (I think, I am a bit of novice).
I will be happy to clarify anything that is unclear, or change this post if necessary, but I think it is a unique question as far as I could see on SO. Additionally if I need to provide more of the codebase I will.
I will also update this post if I find out more about this problem.
Thank you for reading :3.
After reading about this post https://stackoverflow.com/a/53025865/5055963
on SO I found out that it had to do with the permissions in the manifest of the extension.
Adding this line: "://.localhost/*".
Solved the issue for me.

Upload a file to an IPFS node from Google Apps Script

I'm trying to upload a file to an IPFS node using Google Apps Script (GAS) without success.
However, I was able to upload a file successfully using Postman. Unfortunately Postman only gives back the source code snippet closest to GAS as a JavaScript - Fetch code, which is not working as is in GAS.
In GAS, the authentication part is working and I know that because if I'm changing the bearer token, then I'm getting invalid credentials error instead of "Invalid request format".
Test code attached where I'm getting the "Invalid request format" error from the server.
For testing purpose, the file which needs to be uploaded, could be created on the fly with the script, but has to be one from Google Drive eventually.
function test() {
let myHeaders = {'Authorization': 'Bearer ...'};
let fileBlob = Utilities.newBlob('Hello!', 'text/plain', 'TestFile.txt');
let formdata = {'file': fileBlob,
'pinataMetadata': {'name': 'TestFileNewName.txt','keyvalues': {'MetaData1': 'Test1', 'MetaData2': 'Test2'}},
'pinataOptions': {'cidVersion': 0}};
let requestOptions = {
method: 'post',
headers: myHeaders,
papyload: formdata,
muteHttpExceptions: true
};
let url = "https://api.pinata.cloud/pinning/pinFileToIPFS";
let response = UrlFetchApp.fetch(url, requestOptions);
let responeText = JSON.parse(response.getContentText());
Logger.log(responeText);
}
If your access token of Bearer ... is the valid value for using the API, how about the following modification? From the official document, I thought that in the case of your formdata, the values of pinataMetadata and pinataOptions might be required to be the string type.
From:
let formdata = {'file': fileBlob,
'pinataMetadata': {'name': 'TestFileNewName.txt','keyvalues': {'MetaData1': 'Test1', 'MetaData2': 'Test2'}},
'pinataOptions': {'cidVersion': 0}};
To:
let formdata = {
'file': fileBlob,
'pinataMetadata': JSON.stringify({ 'name': 'TestFileNewName.txt', 'keyvalues': { 'MetaData1': 'Test1', 'MetaData2': 'Test2' } }),
'pinataOptions': JSON.stringify({ 'cidVersion': 0 })
};
And also, please modify papyload: formdata, to payload: formdata,. This has already been mentioned by
TheMaster's comment.
References:
Pin File
fetch(url, params)

Unable to generate OAuth 2.0 Access Token from Office365 via JavaScript

I'm trying to pull an access token from Office365's /token identity platform endpoint via OAuth 2.0 client credentials grant flow. I have my app registered, the client ID & secret, etc...
I can make the POST request in Postman and receive the access token without issue:
However, when I try the POST request via JavaScript (by way of Google Apps Script), I receive an error message: AADSTS900144: The request body must contain the following parameter: 'grant_type'
I've already Google'd this error and found a bunch of different solutions, and have tried implementing them to no avail. I imagine this has to do with the URL encoding, but cannot figure it out.
Code:
function getO365() {
// POST Request (To get Access Token)
var tenantID = 'longstringhere'
var appID = 'longstringhere'
var appSecret = 'longstringhere'
var graphScore = 'https://graph.microsoft.com/.default'
var url = 'https://login.microsoftonline.com/' + tenantID + '/oauth2/v2.0/token'
var data = {
'client_id': appID,
'scope': graphScore,
'client_secret': appSecret,
'grant_type': 'client_credentials'
};
var postOptions = {
'method': 'POST',
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
'body': data,
'redirect': 'follow'
};
var authToken = UrlFetchApp.fetch(url, postOptions);
}
The only real difference between my code and the JavaScript Fetch code I pulled off of Postman is:
var urlencoded = new URLSearchParams();
urlencoded.append("client_id", "longstringhere");
urlencoded.append("scope", "https://graph.microsoft.com/.default");
urlencoded.append("client_secret", "longstringhere");
urlencoded.append("grant_type", "client_credentials");
When I try to use URLSearchParams in Google Apps Script, I keep getting this error: ReferenceError: URLSearchParams is not defined
Any ideas? Thanks in advance!
This was resolved by changing 'body' to 'payload' for UrlFetchApp per the documentation. Edited code to reflect the change. Credit to #TheMaster for pointing out my mistake.
'payload': data,//from 'body': data,

Invalid signature Open Bank Project Oauth1.0a

I'm developing a React-Native App with Open Bank Project and I can't use suggested SDKs, not even the nodeJS one as Oauth1.0 is not available in RN.
And I'm stuck with a Bad Signature error on Access Token request '/oauth/token' after passed '/oauth/initiate' and '/oauth/authorize' without any problem.
As specified in docs here before accessing to a Protected Resource we need an Access Token via a POST Request, which gives me the Bad Signature answer.
Here is my code for the request:
getAccessToken(verifier){
let request = {
url: 'https://api.openbankproject.com/oauth/token',
method: 'POST',
data: {
oauth_verifier: verifier,
oauth_token: this.auth.oauth_token,
oauth_token_secret: this.auth.oauth_token_secret
}
}
return fetch(this.url_login, {
method: request.method, //POST
form: request.data,
headers: this.oauth.toHeader(this.oauth.authorize(request))
})
.then((res) => {return res.text()})
.then((txt) => {
console.log('setUID', txt, this.url_login, {
method: request.method,
form: request.data,
headers: this.oauth.toHeader(this.oauth.authorize(request))
})
})
Here is the signed request:
Object {method: "POST", form: Object, headers: Object}
form:
oauth_token:"..."
oauth_token_secret:"..."
oauth_verifier:"71531"
headers:
Authorization:
"OAuth oauth_consumer_key="...", oauth_nonce="3UlQ5dx958tibf6lSg0RUGPQFZeV7b8V", oauth_signature="weyE1lFkoIjAErYLKdSi9SDlCZsNBi7%2BuAkLV2PWePo%3D", oauth_signature_method="HMAC-SHA256", oauth_timestamp="1464248944", oauth_token="...", oauth_token_secret="...", oauth_verifier="71531", oauth_version="1.0""
I've tried with and without Oauth_token_secret, also moving oauth_verifier from body to query but with the same Bad Signature result.
Any idea? thx
You can use oauth module https://github.com/ciaranj/node-oauth
var oauth=require('oauth');
var consumer = new oauth.OAuth(
"https://twitter.com/oauth/request_token", "https://twitter.com/oauth/access_token",
_twitterConsumerKey, _twitterConsumerSecret, "1.0A", "http://127.0.0.1:8080/sessions/callback", "HMAC-SHA1");
then generating signature like this :
var parameters = consumer._prepareParameters("user_access_token", "user_access_token_secret", "http_method", "request_url");
var headers = consumer._buildAuthorizationHeaders(parameters);
parameters array contains signature, also you can build authorization headers if needed. Hope it helps :)

mootools Request class and CORS

I'm trying to use CORS to have a script do an Ajax request to geonames.
My script calls this web service method: http://www.geonames.org/export/web-services.html#findNearby
If you check the response headers of the sample call, they include:
Access-Control-Allow-Origin: *
When I try this with mootools (version 1.4.5 just downloaded):
var urlGeonames = "http://api.geonames.org/findNearbyPlaceName";
var req = new Request({
method: 'get',
url: urlGeonames,
data: {
'lat': '89.18',
'lng': '-0.37',
'username': 'myusername',
'radius': '5'
}
}).send();
then I get an error that says :
XMLHttpRequest cannot load
http://api.geonames.org/findNearbyPlaceName?lat=89.18&lng=-0.37&username=myusername&radius=5.
Origin http://127.0.0.1 is not allowed by Access-Control-Allow-Origin.</pre>
On the other hand, when I try old style Ajax code like this:
invocation = new XMLHttpRequest();
if(invocation)
{
invocation.open('GET', urlFlickr, true);
invocation.onreadystatechange = handler;
invocation.send();
}
then it works and I get the XML response in the XHR responseXML.
I found this post A CORS POST request works from plain javascript, but why not with jQuery? that is similar. But here I'm not dealing with my server so I can only work on the javascript side.
Has anyone worked with CORS and mootools and can help on this issue ?
Thanks so much
JM
Hey man check out mootools more JSONP this will solve your problem:
http://mootools.net/docs/more/Request/Request.JSONP
Also it looks like your forgetting to ask for it in JSON format from geonames.org
Try something like:
var myJSONP = new Request.JSONP({
url: 'http://api.geonames.org/findNearbyPlaceNameJSON',
data: {
'lat': '89.18',
'lng': '-0.37',
'username': 'myusername'
},
onRequest: function(url){
// a script tag is created with a src attribute equal to url
},
onComplete: function(data){
// the request was completed.
console.log(data);
}
}).send();
Hope this helps!
The first answer on this other thread:
MooTools CORS request vs native Javascript
Might help.
Basically, the X-Requested-With header is automatically sent by the Mootools with the request, but the server either has to be configured to accept that header or you can remove it using
delete foo.headers['X-Requested-With'];
Before calling
foo.send();
To allow it by the server, you can add this to the .htaccess file of your script that gives back the JSON data:
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
So yours would look like:
var myJSON = new Request({
url: 'http://api.geonames.org/findNearbyPlaceNameJSON',
data: {
'lat': '89.18',
'lng': '-0.37',
'username': 'myusername'
},
onRequest: function(url){
// a script tag is created with a src attribute equal to url
},
onComplete: function(data){
// the request was completed.
console.log(data);
}
});
delete myJSON.headers['X-Requested-With'];
myJSON.send();