UrlFetchApp Authentication failed Freshbooks - urlfetch

So I am trying to communicate with the freshbooks api by making the sample request detailed on the developers page of freshbooks (http://developers.freshbooks.com/). We are doing token-based authentication as opposed to using OAuth.
I have my code logging the responses to my requests in a spreadsheet. The responses it has been logging are as follows:
<?xml version="1.0" encoding="utf-8"?>
<response xmlns="http://www.freshbooks.com/api/" status="fail">
<error>Authentication failed.</error>
<code>20010</code>
</response>
I have been able to authenticate when using a curl command in console, but not when running the script. Below is the code I used. Left out the logging to spreadsheet part and our specific url and authToken:
// Sample function to call into an API using basic HTTP auth
function freshbooksTest () {
var url = ;
var authToken = ;
var unamepass =authToken+":X";
var digestfull = "Basic "+unamepass;
var payload = '<request method="system.current"></request>';
var options =
{
"method" : "post",
"muteHttpExceptions": true,
"headers" : {"Authorization": digestfull},
"payload" : payload
};
var response = UrlFetchApp.fetch(url, options);
var xml = response.getContentText();
}
I have checked out threads where people are having similar problems, but the solutions were either not applicable to my situation, or have already been tried. Any suggestions are welcome.

Not specifically familiar with UrlFetchApp, but if it doesn't do it for you, you'll need to Base64 encode digestfull before you send it in the header.

Looks like you need to base 64 encode your auth token. Code should look like this:
function freshbooksTest () {
var url = ;
var authToken = ;
var unamepass = authToken+":X";
var digestfull = "Basic "+ Utilities.base64Encode(unamepass);
var payload = '<request method="system.current"></request>';
var options =
{
"method" : "post",
"muteHttpExceptions": true,
"headers" : {"Authorization": digestfull},
"payload" : payload
};
var response = UrlFetchApp.fetch(url, options);
var xml = response.getContentText();
}

Related

Flutter qraphQl issue with setting requesting data from body of api

I am trying to connect to an graphQl api that uses the token as the password in the Basic auth section of the header. I have tried using flutter_graphql but as I only get the token back after the user logs in. I have managed to get logged in using:
String username = "";
String password = token;
String basicAuth = 'Basic' + base64Encode(utf8.encode("$username:$password"));
String projects = "query Projects{Projects{id name}}";
Uri newUri = Uri.parse("$link");
var newResponse = await http.post(newUri, headers: {
"Authorization": basicAuth,
"Content-Type": "application/graphql"
}, body: //I need to get projects here.
);
var newNonJsonData = newResponse.body;
group("Testing the graph ql data after logging in: ", () {
test("Logged in", () {
expect(newResponse.statusCode, 200);
});
test("getting the data from the api", () {
print("non json return:" + newNonJsonData);
});
});
I have tried to set the body as
jsonEncode({
'query' : prjects
})
but the moment I request the data it asks to log in.
Please could someone help!!!

How to convert this curl example to google apps script / javascript? [duplicate]

I have experience making CURL calls in GAS using headers and payload, but I have never done a CURL command using the -u option before. According to the API spec, I must use the -u option. I just don't know how to convert that to GAS. Here is my code so far:
function updateStatus()
{
//Build header.
var header =
{
'Content-Type': 'application/json', //Set content type to JSON.
};
//Put it all together.
var options =
{
'method' : 'get',
'headers' : header
};
//Make Login call to When I work.
var responseGetPlan = UrlFetchApp.fetch('my url', options);
var strResponseGetPlan = responseGetPlan.getContentText();
Logger.log('Get Plan Response: ' + strResponseGetPlan); //Log response.
var parsedData = JSON.parse(strResponseGetPlan); //Parse into JSON format.
var strId = parsedData.id;
Logger.log(strId);
}
curl -u uses Basic authentication, which is a simple base64 encoding of a concatenated "username:password" string. You would send the following as headers.
Authorization: 'Basic ' + Utilities.base64Encode('username:password')
References:
RFC7617
curl Basic Authentication
Utilities

Access to partner.admin_accounts

How we can get access to partner.admin_accounts scope ?
We catch response:
{"code":"unauthorized","message":"This endpoint requires all of the following scopes: partner.admin_accounts"}
When trying to GET
https://api.uber.com/v1/partners/drivers
upd: full code, we using GAS
function uberGET(){
var token = 'my_secret_tocen';
var url = 'https://api.uber.com/v1/partners/drivers';
var header = {'Content-Type': 'application/json',
'Authorization': 'Bearer '+token};
var options = {'method':'GET','headers':header,'muteHttpExceptions': true};
var response = UrlFetchApp.fetch(url,options);
Logger.log(response);
}
upd:
it looks like we need to get full access, but ....
...official support help.uber.com sent us here and on their Twitter :)
upd:
that "official" form:
https://developer.uber.com/products/drivers
is now working((
#Sasa Jovanovic any way for we can ask full access?

Unable to connect HP ALM API via google script

I'm trying to call HPQC API to get some reports but I'm not able to get the QCsession cookie when I call /qcbin/rest/site-session. I successfully authenticated with /qcbin/authentication-point/authenticate but I'm stuck in the next phase.
Not that I can use the API without any trouble with Postman, but my Google script doesn't work.
Here's a look at the call I'm doing :
var headers = { "Accept":"application/xml",
"Content-Type":"application/xml",
"method": "POST",
"headers" : {"Authorization": digestfull },
"muteHttpExceptions": true
};
var resp = UrlFetchApp.fetch(url,headers);
var cookie = resp.getAllHeaders();//['Set-Cookie'];//.split(';')[0].toString();
Logger.log(cookie);
//Get session cookie
param = "/hp/rest/site-session";
var url2 = hpqc + param + api_key;
var payload = "<session-parameters><client-type>REST Client</client-type></session-parameters>";
var headers2 = { "Accept":"application/json",
"Content-Type":"application/xml",
"method": "POST",
"muteHttpExceptions" : true,
"cookie" : cookie,
"body" : payload
};
resp = UrlFetchApp.fetch(url2,headers2);
The first call works fine, but the second gives me the following response :
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Error 401 Authentication failed. Browser based integrations - to login append '?login-form-required=y' to the url you tried to access.</title>
</head>
<body><h2>HTTP ERROR 401</h2>
<p>Problem accessing /qcbin/rest/site-session. Reason:
<pre> Authentication failed. Browser based integrations - to login append '?login-form-required=y' to the url you tried to access.</pre></p><hr><i><small>Powered by Jetty://</small></i><hr/>
It seems that the cookies aren't correctly sent.
Can you please help me find what is wrong with my code ? I'm sorry if it's too obvious, I'm learning to use google script.
Thank you
I changed the following code
var payload = "<session-parameters><client-type>REST Client</client-type></session-parameters>";
var headers2 = { "Accept":"application/json",
"Content-Type":"application/xml",
"method": "POST",
"muteHttpExceptions" : true,
"cookie" : cookie,
"body" : payload
};
with this and it worked
var payload = "<session-parameters><client-type>REST Client</client-type></session-parameters>";
var headers = {// "accept":"application/json",
//"contentType":"application/json",
"method": "POST",
"muteHttpExceptions" : true,
"headers" : {
"Content-type" : "application/xml",
"Accept" : "application/json",
"Cookie" : cookie
},
"payload" : payload
};
Thank you TheMaster for giving me the hint !!

REST request to update GMAIL signature with Domain validation

I've created the below code with some help to access any user's signature on my domain in order to standardize the signature across users. Currently, When I specify method 'PATCH' in the URLFetch parameters, All I get is the sendAs resource of the email I sent, including the old signature. If I specify the PUT method, it removes the signature, but will not set the signature I specified onto the account. Could someone help me see what I am doing wrong?
////////////////////////////////////////////////////FUNCTION SET SIGNATURE////////////////////////////////////////////////////////////////////////
/**
* Authorizes and makes a request to the GMail API.
*/
function setSignature(user)
{
var user = 'me#mydomain.com';
var newSig = '<b>This is my new Signature!</b>';
var service = getService(user);
if (service.hasAccess()) {
var url = 'https://www.googleapis.com/gmail/v1/users/'+user+'/settings/sendAs/'+user;
var payload =
{
"sendAsEmail" : user,
"displayName" : AdminDirectory.Users.get(user).name.fullName,
"type" : "patch",
"replyToAddress" : user,
"signature": newSig
};
var options =
{
"method" : "PUT",
"payload" : payload,
"muteHttpExceptions": true,
"contentType": "ctAPPLICATION_JSON",
"headers": {Authorization: 'Bearer ' + service.getAccessToken()}
};
var response = UrlFetchApp.fetch(url, options);
Logger.log(response.getContentText());
} else {
Logger.log(service.getLastError());
}
}
////////////////////////////////////////////////////FUNCTION VIEW SIGNATURE////////////////////////////////////////////////////////////////////////
function viewSignature(user) { var user = USER_EMAIL;
var service = getService(user);
Logger.log(service.hasAccess());
if (service.hasAccess()) {
var url = 'https://www.googleapis.com/gmail/v1/users/'+user+'/settings/sendAs';
var response = UrlFetchApp.fetch(url, {
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
}
});
var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
} else {
Logger.log(service.getLastError());
}
}
////////////////////////////////////////////////////FUNCTION RESET//////////////////////////////////////////////////////////////////////////////////////
/**
* Reset the authorization state, so that it can be re-tested.
*/
function reset() {
var service = getService();
service.reset();
}
///////////////////////////////////////////////////////////FUNCTION GET SERVICE////////////////////////////////////////////////////////////////////////
/**
* Configures the service.
*/
function getService(user) {
return OAuth2.createService('Gmail:' + user)
// Set the endpoint URL.
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
// Set the private key and issuer.
.setPrivateKey(PRIVATE_KEY)
.setIssuer(CLIENT_EMAIL)
// Set the name of the user to impersonate. This will only work for
// Google Apps for Work/EDU accounts whose admin has setup domain-wide
// delegation:
// https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
.setSubject(user)
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getScriptProperties())
// Set the scope. This must match one of the scopes configured during the
// setup of domain-wide delegation.
.setScope('https://www.googleapis.com/auth/gmail.settings.basic', 'https://www.googleapis.com/auth/gmail.settings.sharing');
}
////////////////////////////////////////////////////FUNCTION CLEAR SIGNATURE////////////////////////////////////////////////////////////////////////
function clearService(){
OAuth2.createService('drive')
.setPropertyStore(PropertiesService.getUserProperties())
.reset();
}
NOTE: OAuth2 Credentials are stored in Constant variables in a separate file, but I have verified that the credentials return valid data.
Thanks,
My apps works, problem is contentType.
Try:
var formData = {'sendAsEmail':user,'type':'patch','signature': newSig}
var options =
{
'method' : 'put',
'muteHttpExceptions': true,
'contentType': 'application/json',
'headers': {Authorization: 'Bearer ' + service.getAccessToken()},
'payload': JSON.stringify(formData)
};