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.
Related
Apologies if this is a silly question, I am very new to programming in general and I have never worked with OAuth before.
I am currently trying to build a Google App Script which interacts with an external service and authenticates using OAuth2.
I am having a lot of trouble with OAuth2... for starters, I'm not sure I am using the correct library for this. I am going off the one recommended by Google for ads script - https://developers.google.com/google-ads/scripts/docs/examples/oauth20-library
I know there is another popular one available in GitHub https://github.com/googleworkspace/apps-script-oauth2
I was not able to use it because everything comes out as 'is not a function', no matter how I add the library, manually or through the built-in feature.
I started building the API call, based on the first library and I had some partial success, I started getting back a 500 error message and I realized my accessToken is null.
function SHICall(){
var tokenUrl = "X/token";
const scriptProperties = PropertiesService.getScriptProperties();
var clientId = scriptProperties.getProperty('CLIENT_ID');
var clientSecret = scriptProperties.getProperty('SECRET');
var opt_scope = "CustomerAPI.Public";
// Access token is obtained and cached.
const authUrlFetch = OAuth2.withClientCredentials(tokenUrl, clientId, clientSecret, opt_scope);
const url = "X";
Logger.log(authUrlFetch);
var options = {
headers: { 'Content-Type': "application/json", 'Accept': "application/json"},
muteHttpExceptions: true,
method: "GET",
contentType: "application/json",
validateHttpsCertificates: false,
};
// Use access token in each request
const response = authUrlFetch.fetch(url, options);
// ... use response
Logger.log(response);
}
Any clue why the token is coming back as null? I based my API Call on google's documentation again https://developers.google.com/google-ads/scripts/docs/features/third-party-apis#oauth_2
I am trying to use the new Google Docs API using Google Apps Script. Since new API is not yet available as an extended service, I am trying to do it using UrlFetchApp() but failing.
Apologies for my naive attempt here:
function apiCall(){
var API_KEY = 'YOUR_API_KEY';
var username = 'YOUR_USERNAME';
var password = 'YOU_PASSWORD';
var DOC_ID = 'YOUR_DOC_ID';
var root = 'https://docs.googleapis.com/v1/documents/';
var endpoint = DOC_ID;
var query = '?key=' + API_KEY;
var params = {
'method': 'GET',
'muteHttpExceptions': true,
'headers': {
'Authorization': 'Basic ' + Utilities.base64Encode(username + ':' + password)
}
};
var response = UrlFetchApp.fetch(root + endpoint + query, params);
var data = response.getContentText();
var json = JSON.parse(data);
Logger.log(json);
}
I get the following response:
{error={code=401, message=Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or another valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project., status=UNAUTHENTICATED}}
Can someone point to the right direction, where I can find some documentation how to use Google Docs API in Google Apps Script.
If you own the document then you don't need to leverage an API key. Also, instead of using Basic authentication you can leverage the built-in Bearer OAuth token as follows:
/**
* Get `Document` resource object from Google Docs REST API.
*
* #param {String} docId - A Google Document Id
*
* #return {Document} A Document resource object.
*/
function getDocumentResouce(docId) {
return JSON.parse(UrlFetchApp.fetch(
"https://docs.googleapis.com/v1/documents/" + docId,
{
"headers": {
"Authorization":"Bearer " + ScriptApp.getOAuthToken()
}
}
)
);
}
Note: GET is the default HTTP request method used by UrlFetchApp.fetch() so you don't need to define it in the options object.
ADDENDUM
As Tanaike stated in the comments you'll need to manually add the relevant scopes (in addition to the ones you already have enabled) to your manifest JSON.
First check your project properties to get the list of existing scopes via the menu
File > Project Properties > Scopes. You need to add those scopes, as well as one of the relevant document scopes (listed in the documentation) to your manifest.
The following links provide the information you'll need to manage your manifest and scopes:
https://developers.google.com/apps-script/concepts/manifests
https://developers.google.com/apps-script/concepts/scopes
I am getting "Error Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup" in google sheets with using URL Shortener API (image as below)
Below is my code in Script Editor
function shortenURL(urlField) {
var toShorten = UrlShortener.newUrl().setLongUrl(urlField);
var shortened = UrlShortener.Url.insert(toShorten);
return shortened.getId();
}
I have bonded to the API through Google Sheets build-in setting from "Cloud Platform Project", enabled URL Shortener API in "Advanced Google Services", enabled it in Google API Console, and created both API and OAuth (image as below). Besides, I was just using it for less than 20 cells in the Google Sheets, and so I am sure it is way less than the quote given by Google.
Cloud Platform Project
Advanced Google Services
Enable in Google API Console
If I use the below code (mentioned here), it works fine.
However, I want the script to run automatically as the function instead of by clicking the button. Therefore, I still want to solve the error.
function onOpen() {
SpreadsheetApp.getUi()
.createMenu("Shorten")
.addItem("Go !!","rangeShort")
.addToUi()
}
function rangeShort() {
var range = SpreadsheetApp.getActiveRange(), data = range.getValues();
var output = [];
for(var i = 0, iLen = data.length; i < iLen; i++) {
var url = UrlShortener.Url.insert({longUrl: data[i][0]});
output.push([url.id]);
}
range.offset(0,1).setValues(output);
}
I found some post mentioned the solution to this error is to apply authentication to the requests to Google. However, I have already created API key and OAuth and bond them to Google Sheets through those Google Sheets build-in setting.
Is there any solution to the error?
If the error occurs due to authentication issue, how I can apply the authentication in addition to those setting I have already done?
Try sending a POST request to UrlShortener API endpoint instead of using the UrlShortener service in Apps Script. With UrlShortener.Url.insert(), I quickly hit the usage quota.
Append the API url with the 'key' parameter and set it equal to the API key you obtained from Developer console.
In the body of your POST request, set 'muteHttpExceptions' to 'true' to log all error messages as beautified JSON.
var API_KEY = "YOUR_API_KEY";
function shortenUrl(longUrl) {
var apiEndpoint = "https://www.googleapis.com/urlshortener/v1/url?key=" + API_KEY;
var data = {
"longUrl": longUrl
}
var options = {
"method": "post",
"contentType": "application/json",
"muteHttpExceptions": true,
"payload": JSON.stringify(data)
};
var response = UrlFetchApp.fetch(apiEndpoint, options).getContentText();
var data = JSON.parse(response);
return data.id;
}
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)
};
I'm trying to make a simple GET request to a site with a valid SSL certificate using UrlFetchApp, but I continuously encounter this error:
ScriptError: SSL Error https://dev.kaizena.com/api/config
Interestingly enough, the same request works as expected when I make a request to https://kaizena.com/api/config
Here's the code I'm using:
var url = "https://dev.kaizena.com/api/config";
var payload = JSON.stringify(data);
var headers = { "Accept":"application/json",
"Content-Type":"application/json"//,
};
var options = { "method":"GET",
"contentType" : "application/json",
"headers": headers,
"payload" : payload
}
var response = UrlFetchApp.fetch(url);
Again, the code works as expected if I change the URL to https://kaizena.com/api/config (which also has a valid SSL certificate). Could someone let me know specifically what an "SSL Error" is?
Thanks,
Edward
You can use validateHttpsCertificates to ignore this SSL error.
var options = {
'validateHttpsCertificates' : false
};
var response = UrlFetchApp.fetch(url, options);
It looks like the issue is with Google not recognizing the provider of the SSL Certificate I used. For reference, I was using PositiveSSL, which provided a valid certificate but didn't seem to make Apps Script very happy. I switched to RapidSSL today and now it all works.
Thank you all for the help.
The syntax for urlFetchApp is:
fetch(url)
or
fetch(url, params)
urlFetchApp
You are creating a payload, header and options, but then not using them.
var response = UrlFetchApp.fetch(url);
Should be:
var response = UrlFetchApp.fetch(url, options);