Google scripts basic authentication - google-apps-script

Im trying to log the json data after making an api call however Google always asks for authorisation and I need it to automatically authenticate using the api key provided .
Putting the url into the browser directly , I only need to supply the api key as the username .
The code im using is as follows :
function testapi(){
var encode = Utilities.base64Encode('apikey', Utilities.Charset.UTF_8);
Logger.log(encode);
var option = {
headers : {
Authorization: "Basic "+ encode
}
}
var url = "https://apiurl.json";
var response = UrlFetchApp.fetch(url, option).getContentText()
response = JSON.parse(response);
Logger.log(response);
}

Related

Api call works with curl but not with google apps script, what am I missing? [duplicate]

This question already exists:
How to convert this curl example to google apps script / javascript? [duplicate]
Closed 1 year ago.
So this part works:
function authenticateToggl()
{
url = "https://api.track.toggl.com/api/v8/me";
//Put it all together.
var options =
{
'method' : 'get',
'headers' : {"Authorization": 'Basic ' + Utilities.base64Encode('email#gmail.com:mypassword')},
};
//Make Login call to When I work.
var responseGetPlan = UrlFetchApp.fetch(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.data.api_token;
return strId;
}
That returned me a string api token, which I can use in api curl calls like this:
curl -v -u c8f4c3TOKENe5a580bfeab:api_token -X GET https://api.track.toggl.com/api/v8/workspaces/1001455/projects
Doing that I appropriately got back my list of projects per the api docs.
But when I tried to translate that into google apps script, it fails. I'm sure it is that my header is formatted wrong?
function nextStep(){
UrlFetchApp.fetch('https://api.track.toggl.com/api/v8/workspaces/1001455/projects', {//
'headers': {'Authorization': "Basic c8f4c3TOKENe5a580bfeab:api_token"},
'method':'get'
});
}
I get back a 403 authentication error. Does the word basic not apply here? using the same url, method, and token.
It seems you need to convert your string token to base64 encoding,
function nextStep(){
//API Key requires base64 encoding. Use Google Apps Scripts built in method
var base64token = Utilities.base64Encode("c8f4c3TOKENe5a580bfeab:api_token");
UrlFetchApp.fetch('https://api.track.toggl.com/api/v8/workspaces/1001455/projects', {
'headers': {'Authorization': "Basic "+base64token},
'method':'get'
});
}
Additional References:
Github - Google-Apps-Scripts-Toggl-Request
Github - toggl-appscript

Can Google Sites API still be authorized?

I tested it in the Google OAuth 2.0 Playground and it looked like I could return info from the site, but when I set up the OAuth2 code from Github, I can't seem to do a UrlFetchApp request as I get
the error returned code 403. Truncated server response: Not authorized to access this feed
I am not sure if this is because it is not enabled in the API console, but I can't find it there or under Advanced Google Services.
This is the section of code I am falling down at:
var service = getService();
if (service.hasAccess()) {
Logger.log("initial xml has access "service.hasAccess());
var headers = {
"Authorization": "Bearer " + service.getAccessToken()
};
var MyAttachmentsURL = 'https://sites.google.com/feeds/content/[DOMAIN]/[SITE NAME]?kind=attachment';
var response = UrlFetchApp.fetch(MyAttachmentsURL, headers);
};
The script from Github worked for me and I authorized when the message came up. This is what is in my scope tab:
7 OAuth Scopes required by the script:
https://sites.google.com/feeds
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/script.container.ui
https://www.googleapis.com/auth/script.external_request
https://www.googleapis.com/auth/script.scriptapp
https://www.googleapis.com/auth/spreadsheets
https://www.googleapis.com/auth/userinfo.email
According to the Protocol Guide's "Authorizing requests with OAuth 2.0" You must activate the Google Sites API in the API Console if you can see that option (Step 2).
The only other issue I can see is the requiring to specify a version as GData-Version: 1.4.
So your code would change to something like this:
var service = getService();
if (service.hasAccess()) {
Logger.log("initial xml has access "service.hasAccess());
var headers = {
"GData-Version": "1.4",
"Authorization": "Bearer " + service.getAccessToken()
};
var MyAttachmentsURL = 'https://sites.google.com/feeds/content/[DOMAIN]/[SITE NAME]?kind=attachment';
var response = UrlFetchApp.fetch(MyAttachmentsURL, headers);
};
As long as the scope is mentioned in the code, it doesn't need to be passed, so that wasn't the issue. This was one of many variations I had been trying and I blame missing the post method on it being the wee hours. This code works (for now).
var service = getService();
if (service.hasAccess()) {
Logger.log("initial xml has access "+service.hasAccess());
var headers = {
// "GData-Version" : "1.4",
"Authorization" : "Bearer "+service.token_.access_token
};
var params = {"headers": headers, 'method':'get', 'muteHttpExceptions':true};
var MyAttachmentsURL = 'https://sites.google.com/feeds/content/[DOMAIN]/[SITE NAME]?kind=attachment';
var response = UrlFetchApp.fetch(MyAttachmentsURL, params);
};
It appears that "GData-Version" : "1.4" is returned in the response header so is not needed in the request. What is needed is the access token and although all the other API's seem to be able to make use of .getAccessToken, I had to amend this to .token_.access_token - this may be just for Google Sites.
I appreciate those who had a look at this and thank you Chris for responding.

AUTHENTICATION_FAILED when querying CloudKit public database with CloudKit Web Services API in Google Apps Script

I'm trying to use the CloudKit Web Services API to fetch Article records from my production CloudKit container's public database within Google Apps Script.
My request is based on the documentation on this page.
Here's my code:
// variables for the CloudKit request URL
var path = "https://api.apple-cloudkit.com";
var version = "1";
var container = "iCloud.com.companyname.My-Container-Name";
var environment = "production";
var database = "public";
var token = "8888888888888_my_actual_token_88888888888888888"
function showArticles() {
// assemble the URL
var url = path + "/database/" + version + "/" + container + "/" + environment + "/" + database + "/records/query?ckAPIToken=" + token;
// specify the record type to query
var query = {
recordType: "Article"
};
// specify the payload for the POST request
var payload = {
query : query
};
// set up the fetch options for the fetch request
var options = {
method : "POST",
payload : payload
};
// make the request
var response = UrlFetchApp.fetch(url, options);
Logger.log(response);
}
UrlFetchApp.fetch(url, options) fails with this error:
Request failed for https://api.apple-cloudkit.com/database/1/iCloud.<?>-Container-Name/development/public/records/query?ckAPIToken=8888888888888_my_actual_token_88888888888888888 returned code 401. Truncated server response: {"uuid":"7d8a8547-ad08-4090-b4b3-917868a42f6f","serverErrorCode":"AUTHENTICATION_FAILED","reason":"no auth method found"} (use muteHttpExceptions option to examine full response) (line 30, file "Code")
I've been troubleshooting for a few hours and I can't figure out what I'm doing wrong. I've tried it with a separate token on my development environment, too, and the same thing happens.
This page mentions the ckWebAuthToken parameter and says "if omitted and required, the request fails," but I can't find anything that says what requests require a ckWebAuthToken. I'm assuming I don't need ckWebAuthToken since the records I'm trying to access are in my container's public database, and I'm getting an AUTHENTICATION_FAILED error rather an AUTHENTICATION_REQUIRED error.
One part that confuses me is this URL that comes up in the error message:
https://api.apple-cloudkit.com/database/1/iCloud.<?>-Container-Name/development/public/records/query?ckAPIToken=8888888888888_my_actual_token_88888888888888888
I would expect it to be:
https://api.apple-cloudkit.com/database/1/iCloud.com.companyname.My-Container-Name/development/public/records/query?ckAPIToken=8888888888888_my_actual_token_88888888888888888
But I can't tell if that's actually the URL that's being requested, and when I log the url variable everything looks fine.
Thanks in advance for any troubleshooting tips or solutions!
UPDATE
I tried using Postman, and the request worked with same endpoint and POST data. It looks like the container component of the URL is getting corrupted by the Google Apps Script UrlFetchApp.fetch() method. The <?> seems to only show up when com. is in the URL.
I'm not sure why this is the answer, but I was able to get it working by using JSON.stringify() on the payload in options:
var options = {
method : "POST",
payload : JSON.stringify(payload)
};

UrlFetch from Google Sheet exportLink['application/pdf'] not returning PDF data

I create and send a periodic email as an update from a Google Sheet. For various client reasons this is done 3 ways, as a link to the Sheet, and as attachments (PDF and XLSX).
This was working 'til recently. The XSLX attachment still works, but the PDF is no longer sent as a response to a UrlFetch to the file.exportLinks('application/pdf') url. No matter what the request headers it always returns as Content-Type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Did something else undocumented change that I am missing here?
function exportAsPDF(spreadsheetId) {
spreadsheetId = spreadsheetId || 'SECRET_ID';
var file = Drive.Files.get(spreadsheetId),
url = file.exportLinks['application/pdf'];
url += '&format=pdf&size=7&fzr=true&portrait=true&fitw=true&gid=0&gridlines=false&printtitle=false&sheetnames=false&pagenum=UNDEFINED&attachment=true'
var token = ScriptApp.getOAuthToken(),
response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var headers = response.getAllHeaders(); // revealing content-type returned isn't pdf
var pdfBlob = response.getBlob().getAs('application/pdf');
var pdfString = pdfBlob.getDataAsString(); // this naturally throws an error
return response.getBlob(); // this returns to the send mail script
}
I'm able to get PDFs using the utility from Convert all sheets to PDF with Google Apps Script.
That working script modifies the spreadsheet's edit URL into an export URL, which looks like:
https://docs.google.com/spreadsheets/d/<%SS-ID%>/export?exportFormat=pdf...
The advanced Drive service gives an export URL formatted like:
https://docs.google.com/spreadsheets/export?id=<%SS-ID%>&exportFormat=pdf...
I'd expect the URL provided by exportLinks to be more reliable than the hack in the working script. Apparently, it's not.
This has been raised as Issue 5114. Star it to receive updates.

Trello API Moving Card to another List using Google Apps Script

I trying to use Google Apps Script to move a filtered set of cards from one list to another in Trello using their API and this method:
https://trello.com/docs/api/card/index.html#put-1-cards-card-id-or-shortlink-idlist
But I keep getting the following error message:
Request failed for returned code 404. Truncated server response:
Cannot PUT /1/cards/54aa79112b9cdbb78fe43abf/5419475e4948228f2be857bd
My code looks like this:
var url = 'https://api.trello.com/1/cards/'+*ID OF CARD TO BE MOVED*+'/'+*ID OF LIST TO MOVE CARD TO*
var options = {
"method": "PUT",
"oAuthServiceName": "trello",
"oAuthUseToken": "always"
};
UrlFetchApp.fetch(url, options);
Any idea on what I am doing wrong? Do I need to add a payload to the options (so far have only done get and pull requests and it has all worked via the url rather than a payload) if so what would that be the documentation isn't that clear.
Otherwise any other thoughts on what the problem might be
The route you're trying to use is described as PUT /1/cards/[card id or shortlink]/idList - in this specific case, it looks like you want PUT /1/cards/54aa79112b9cdbb78fe43abf/idList. Then, the payload is described in the Arguments section - there should be a single argument named value, and its value is the id of the list.
I'm new in app scritps but i have this solution for your problem
function UpdateTrelloCard() {
var IDcard = "..."
var idafterlist = "...";
var options = {
'method' : 'put',
};
var response = UrlFetchApp.fetch(url + "cards/" + IDcard + "?idList=" + idafterlist + "&key=" + api_key + "&token=" + api_token, options);
var lists = JSON.parse((response.getContentText()));
Logger.log(idtrello)
Logger.log(lists)
}