I am trying to use Google Ads on Google Apps Script using this guide. I created client id and client secret on Google Console's API & Services.
Not too sure if this configuration is correct but the account is linked to Google Apps Script as I have pagespeed insights as well and there are some requests on the dashboard. I added https://www.googleapis.com/auth/drive as the scope. Again not too sure if I should add Google Ads to the scope. Lastly, got my refresh token from Google Auth playground. When I run the script above I got the following error:
Error: No access token received: {
"error": "invalid_client",
"error_description": "Unauthorized"
}
authenticate_ # test.gs:120
withRefreshToken # test.gs:144
initializeOAuthClient # test.gs:28
Honestly not too sure what I am doing wrong here so any help would be very much appreciated. Thank you.
Edit
Codes:
//From Google Console API & Services
var CLIENT_ID = '"MY_CLIENT_ID';
var CLIENT_SECRET = 'MY_CLIENT_SECRET';
//From Google Authplayground
var REFRESH_TOKEN = 'REFRESH_TOKEN';
// Enter scopes which should match scopes in File > Project properties
// For this project, e.g.: https://www.googleapis.com/auth/drive
var SCOPES = "https://www.googleapis.com/auth/adwords";
// Script ID taken from 'File > Project Properties'
var SCRIPT_ID = 'MY_SCRIPT_ID';
var authUrlFetch;
// Call this function just once, to initialize the OAuth client.
function initializeOAuthClient() {
if (typeof OAuth2 === 'undefined') {
var libUrl = 'https://developers.google.com/google-ads/scripts/docs/examples/oauth20-library';
throw Error('OAuth2 library not found. Please take a copy of the OAuth2 ' +
'library from ' + libUrl + ' and append to the bottom of this script.');
}
var tokenUrl = 'https://accounts.google.com/o/oauth2/token';
authUrlFetch = OAuth2.withRefreshToken(tokenUrl, CLIENT_ID, CLIENT_SECRET,
REFRESH_TOKEN, SCOPES);
}
/**
* Execute a remote function.
* #param {string} remoteFunctionName The name of the function to execute.
* #param {Object[]} functionParams An array of JSON objects to pass to the
* remote function.
* #return {?Object} The return value from the function.
*/
function executeRemoteFunction(remoteFunctionName, functionParams) {
var apiParams = {
'function': remoteFunctionName,
'parameters': functionParams
};
var httpOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
payload: JSON.stringify(apiParams)
};
var url = 'https://script.googleapis.com/v1/scripts/' + SCRIPT_ID + ':run';
var response = authUrlFetch.fetch(url, httpOptions);
var data = JSON.parse(response.getContentText());
// Retrieve the value that has been returned from the execution.
if (data.error) {
throw Error('There was an error: ' + response.getContentText());
}
return data.response.result;
}
// Paste in OAuth2 library here, from:
// https://developers.google.com/google-ads/scripts/docs/examples/oauth20-library
I have pasted the oauth2.0 library under the codes above.
Edit 2
I fixed the part of function initializeOAuthClient. It now shows execution complete, but when I try to run function executeRemoteFunction I am getting TypeError: Cannot read property 'fetch' of undefined. I am guessing I have to input remoteFunctionName and functionParams but where do I find them?
Related
I'm trying execute a job on BigQuery on a VPC project using App Scripts.
My goal is store the result in an array to create a dynamic prompt for DataStudio using community connectors
Using the following code:
function runQuery() {
var sql = "SELECT Distinct ss_cd FROM `vf-pt-ngbi-dev-gen-03.AEAD_DataSet_test.d_customer` WHERE end_dttm IS NOT NULL";
var queryResults;
var projectNumber = 'projectNumber'
// Inserts a Query Job
try {
var queryRequest = BigQuery.newQueryRequest();
queryRequest.setQuery(sql).setTimeoutMs(100000);
queryResults = BigQuery.Jobs.query(queryRequest, projectNumber);
}
catch (err) {
Logger.log(err);
return;
}
Since this is a VPC project I need to use a Service Account to perform this request?
However, I would like to know how to add this authorization?
Or exists another approach to execute a BigQuery job on a VPC project and store the results in an array?
You can get the service account token in apps script (see reference) then use that token for the REST API via UrlFetchApp.
Sample:
function runQuery() {
// ...
var service = getService();
if (service.hasAccess()) {
sendQuery(service);
}
// ...
}
function sendQuery(service){
var projectId = 'projectID';
var url = 'https://bigquery.googleapis.com/bigquery/v2/projects/' + projectId + '/queries';
// see request body for reference
// https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#QueryRequest
var body = {
// ...
}
var options = {
"method": "post",
"headers": {
"Authorization": "Bearer " + service.getAccessToken()
},
"contentType": "application/json",
"payload": JSON.stringify(body)
};
var response = UrlFetchApp.fetch(url, options);
}
// direclty copied from https://github.com/googleworkspace/apps-script-oauth2/blob/master/samples/GoogleServiceAccount.gs
function getService() {
return OAuth2.createService('BigQuery:' + USER_EMAIL)
// Set the endpoint URL.
.setTokenUrl('https://oauth2.googleapis.com/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_EMAIL)
// 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/bigquery');
}
References:
BigQuery REST API
Creation of Service Account
Get Service Account Token
Note:
See a question containing a code what yours should look like.
I'm trying to used Google Apps Script to pull Questrade account information into a Google sheets spreadsheet. I've added the oAuth2 library from GitHub(https://github.com/googleworkspace/apps-script-oauth2) then mostly copy and pasted (with minor edits) from the example code.
The weird thing is this code has worked, exactly how it is, but a day later it no longer works and returns the following:
Exception: Request failed for https://api01.iq.questrade.com returned code 401. Truncated server response: {"code":1017,"message":"Access token is invalid"} (use muteHttpExceptions option to examine full response)
My Google Apps Script is posted below. I've only removed my Questrade Client_ID and Google Script Script_ID. I have three buttons in my spreadsheet which I've linked to functions in the script:
Button 1 - QT oAuth - calls showSidebar
Button 2 - Load Account Info - calls makeRequest
Button 3 - QT Logout - calls logout
Typically, I press the QT Logout button to reset 0Auth2 services then I press the QT oAuth button. This seems to successfully go through the authorization process. I then press the Load Account Info button and about 99 times out of 100 I get the invalid access token message. I don't know if it's relevant, but when I log into Questrades API hub I can see that the script is adding an authorization after the QT oAuth button is pressed but it seems to disappear after about a minute.
The script:
function getQTService() {
// Create a new service with the given name. The name will be used when
// persisting the authorized token, so ensure it is unique within the
// scope of the property store.
return OAuth2.createService('QT')
// Set the endpoint URLs.
.setAuthorizationBaseUrl('https://login.questrade.com/oauth2/authorize')
.setTokenUrl('https://login.questrade.com/oauth2/token')
// Set the client ID and secret.
.setClientId('Client_ID')
.setClientSecret(' ') //there is no client secret but oAuth2 requires one
// Set the name of the callback function in the script referenced
// above that should be invoked to complete the OAuth flow.
.setCallbackFunction('authCallback')
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getUserProperties())
.setCache(CacheService.getUserCache())
// Set the scopes to request (space-separated for Google services).
.setScope('read_acc')
}
function showSidebar() {
var QTService = getQTService();
if (!QTService.hasAccess()) {
var authorizationUrl = QTService.getAuthorizationUrl();
var template = HtmlService.createTemplate(
'Authorize. ' +
'Reopen the sidebar when the authorization is complete.');
template.authorizationUrl = authorizationUrl;
var page = template.evaluate();
SpreadsheetApp.getUi().showSidebar(page);
} else {
// ...
}
}
function authCallback(request) {
var QTService = getQTService();
var isAuthorized = QTService.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('Success! You can close this tab.');
} else {
return HtmlService.createHtmlOutput('Denied. You can close this tab');
}
}
function makeRequest() {
var QTService = getQTService();
var token = QTService.getAccessToken();
var spreadsheet = SpreadsheetApp.openById("Script_ID");
// Get account number
var response = UrlFetchApp.fetch('https://api01.iq.questrade.com/v1/accounts',{
headers: {
Authorization: 'Bearer ' + token
}
});
var json = response.getContentText();
var accountdata = JSON.parse(json);
var j = 0;
while(j < accountdata.accounts.length) {
var Account_num = accountdata.accounts[j].number;
var Account_type = accountdata.accounts[j].type;
var sheet = spreadsheet.getSheetByName(Account_type);
// GET CASH BALANCE
var response = UrlFetchApp.fetch('https://api01.iq.questrade.com/v1/accounts/' + Account_num + '/balances',{
headers: {
Authorization: 'Bearer ' + token
}
});
json = response.getContentText();
var balancedata = JSON.parse(json);
var i = 0;
while(balancedata.perCurrencyBalances[i].currency != 'CAD') {
i=i+1;
}
//send cash value to spreadsheet
sheet.getRange("G1").setValue(balancedata.perCurrencyBalances[i].cash);
// GET POSITIONS
var response = UrlFetchApp.fetch('https://api01.iq.questrade.com/v1/accounts/' + Account_num + '/positions',{
headers: {
Authorization: 'Bearer ' + token
}
});
json = response.getContentText();
var positionsdata = JSON.parse(json);
var num_of_positions = positionsdata.positions.length;
var i = 0;
while(i < num_of_positions) { //this loop is not that smart assumes the positions are where I specify, fix later
if(positionsdata.positions[i].symbol == 'VCN.TO'){
sheet.getRange("D5").setValue(positionsdata.positions[i].openQuantity);
}
if(positionsdata.positions[i].symbol == 'VUN.TO') {
sheet.getRange("D6").setValue(positionsdata.positions[i].openQuantity);
}
if(positionsdata.positions[i].symbol == 'VIU.TO') {
sheet.getRange("D7").setValue(positionsdata.positions[i].openQuantity);
}
if(positionsdata.positions[i].symbol == 'VEE.TO') {
sheet.getRange("D8").setValue(positionsdata.positions[i].openQuantity);
}
i=i+1;
}
j=j+1;
}
//send cash value to spreadsheet
// sheet.getRange("G1").setValue(data.perCurrencyBalances[i].cash);
}
function logout() {
var service = getQTService();
service.reset();
}
Any advice on what might be going wrong here would be greatly appreciated.
I don't think you can rely on using api01. I think you have to extract the api_server from the auth call that gives you a token (or at least I did this using the example on https://www.questrade.com/api/documentation/getting-started with refresh_token). My last 3 refresh_token auths for a bearer have yielded the api06 endpoint. I took your code and with the oauth authorizing and using api06 it works fine.
The magic sauce is var api_server = QTService.getToken().api_server;
I've successfully made my GAS for tweet with OAuth1. It's known that OAuth1 GAS library is deprecated, so I'm trying to migrate to OAuth2 library.
I saw a few changes, but I don't get the correct way to authorize my request with this.
The main questions I have right now are:
Bearer Token replace in OAuth2 to key&access tokens in OAuth1?
I don't need key&access to authorize rquest? I'm base on example of the Google developers's site itself
For more clarity, I put the code, extracted from Google developers's site, adapted for my propouses:
// Call this function just once, to initialize the OAuth client.
function initializeOAuthClient() {
if (typeof OAuth2 === 'undefined') {
var libUrl = 'https://developers.google.com/google-ads/scripts/docs/examples/oauth20-library';
throw Error('OAuth2 library not found. Please take a copy of the OAuth2 ' +
'library from ' + libUrl + ' and append to the bottom of this script.');
}
var tokenUrl = 'https://api.twitter.com/oauth2/token';
authUrlFetch = OAuth2.withClientCredentials(
tokenUrl, CONSUMER_KEY, CONSUMER_SECRET);
}
function sendTweet(status) {
var service = accessProtectedResource(SERVICE_UPDATE_URL, "post");
if (service.hasAccess()) {
var url = 'https://api.twitter.com/1.1/statuses/update.json?include_entities=true&status=' + percentEncode(status);
var response = service.fetch(url);
//var result = JSON.parse(response.getContentText());
return response;
}
}
/**
* Attempts to access a non-Google API using a constructed service
* object.
*
* If your add-on needs access to non-Google APIs that require OAuth,
* you need to implement this method. You can use the OAuth1 and
* OAuth2 Apps Script libraries to help implement it.
*
* #param {String} url The URL to access.
* #param {String} method_opt The HTTP method. Defaults to GET.
* #param {Object} headers_opt The HTTP headers. Defaults to an empty
* object. The Authorization field is added
* to the headers in this method.
* #return {HttpResponse} the result from the UrlFetchApp.fetch() call.
*/
function accessProtectedResource(url, method_opt, headers_opt) {
var service = getOAuthService();
var maybeAuthorized = service.hasAccess();
if (maybeAuthorized) {
// A token is present, but it may be expired or invalid. Make a
// request and check the response code to be sure.
// Make the UrlFetch request and return the result.
var accessToken = service.getAccessToken();
var method = method_opt || 'post';
var headers = headers_opt || {};
headers['Authorization'] =
Utilities.formatString('Bearer %s', accessToken);
var resp = UrlFetchApp.fetch(url, {
'headers': headers,
'method' : method,
'muteHttpExceptions': true, // Prevents thrown HTTP exceptions.
});
var code = resp.getResponseCode();
if (code >= 200 && code < 300) {
return resp.getContentText("utf-8"); // Success
} else if (code == 401 || code == 403) {
// Not fully authorized for this action.
maybeAuthorized = false;
} else {
// Handle other response codes by logging them and throwing an
// exception.
console.error("Backend server error (%s): %s", code.toString(),
resp.getContentText("utf-8"));
throw ("Backend server error: " + code);
}
}
if (!maybeAuthorized) {
// Invoke the authorization flow using the default authorization
// prompt card.
CardService.newAuthorizationException()
.setAuthorizationUrl(service.getAuthorizationUrl())
.setResourceDisplayName("Display name to show to the user")
.throwException();
}
}
/**
* Create a new OAuth service to facilitate accessing an API.
* This example assumes there is a single service that the add-on needs to
* access. Its name is used when persisting the authorized token, so ensure
* it is unique within the scope of the property store. You must set the
* client secret and client ID, which are obtained when registering your
* add-on with the API.
*
* See the Apps Script OAuth2 Library documentation for more
* information:
* https://github.com/googlesamples/apps-script-oauth2#1-create-the-oauth2-service
*
* #return A configured OAuth2 service object.
*/
function getOAuthService() {
return OAuth2.createService('SERVICE_NAME')
.setAuthorizationBaseUrl('SERVICE_AUTH_URL')
.setTokenUrl('SERVICE_AUTH_TOKEN_URL')
.setClientId('CLIENT_ID')
.setClientSecret('CLIENT_SECRET')
.setScope('SERVICE_SCOPE_REQUESTS')
.setCallbackFunction('authCallback')
.setCache(CacheService.getUserCache())
.setPropertyStore(PropertiesService.getScriptProperties())
}
/**
* Boilerplate code to determine if a request is authorized and returns
* a corresponding HTML message. When the user completes the OAuth2 flow
* on the service provider's website, this function is invoked from the
* service. In order for authorization to succeed you must make sure that
* the service knows how to call this function by setting the correct
* redirect URL.
*
* The redirect URL to enter is:
* https://script.google.com/macros/d/<Apps Script ID>/usercallback
*
* See the Apps Script OAuth2 Library documentation for more
* information:
* https://github.com/googlesamples/apps-script-oauth2#1-create-the-oauth2-service
*
* #param {Object} callbackRequest The request data received from the
* callback function. Pass it to the service's
* handleCallback() method to complete the
* authorization process.
* #return {HtmlOutput} a success or denied HTML message to display to
* the user. Also sets a timer to close the window
* automatically.
*/
function authCallback(callbackRequest) {
var authorized = getOAuthService().handleCallback(callbackRequest);
if (authorized) {
return HtmlService.createHtmlOutput(
'Success! <script>setTimeout(function() { top.window.close() }, 1);</script>');
} else {
return HtmlService.createHtmlOutput('Denied');
}
}
/**
* Unauthorizes the non-Google service. This is useful for OAuth
* development/testing. Run this method (Run > resetOAuth in the script
* editor) to reset OAuth to re-prompt the user for OAuth.
*/
function resetOAuth() {
getOAuthService().reset();
}
function main() {
try {
let result = sendTweet("Este va a ser un gran día!\n https://www.instagram.com/amos_oficialba/");
Logger.log("Resultado: " + result);
}
catch(err) {
console.log(err["stack"]);
}
}
Native support was removed from OAuthConfig, but that does not prevent your app to make an OAuth 1 request to external APIs. The open source library OAuth1 for Apps Script was created as a replacement in case you were using OAuthConfig before.
To Tweet from Google Apps Script with the OAuth1 for Apps Script library:
You need to setup the callback URL in your Twitter Developer portal. When using this library, the callback URL will always be in the format https://script.google.com/macros/s/YOUR_SCRIPT_ID/usercallback. You will need to replace YOUR_SCRIPT_ID with, well, your script's ID.
In Google Apps Script, go to the File menu and select Project properties. Take a note of your script ID.
In the Twitter Developer portal, select your app, then click Edit under Authentication settings.
Add the callback URL, then click Save when done:
Back in Google Apps Script, select the Resources menu, then click Libraries.
In the Libraries window, import the OAuth1 library by typing its ID 1CXDCY5sqT9ph64fFwSzVtXnbjpSfWdRymafDrtIZ7Z_hwysTY7IIhi7s, then click Add.
Select the latest version (18 at the time of writing)
Once done, use this script to setup a valid Tweet request. Replace CONSUMER_KEY and CONSUMER_SECRET with the API key and secret for your app; replace TOKEN, and TOKEN_SECRET with your user's access token and access token secret.
var CONSUMER_KEY = 'your consumer key';
var CONSUMER_SECRET = 'your consumer secret';
var TOKEN = 'your access token';
var TOKEN_SECRET = 'your access token secret';
/**
* Authorizes and makes a request to the Twitter API.
*/
function run() {
var service = getService();
Logger.log(service.getCallbackUrl())
if (service.hasAccess()) {
var url = 'https://api.twitter.com/1.1/statuses/update.json';
var payload = {
status: 'just setting up my google apps script'
};
var response = service.fetch(url, {
method: 'post',
payload: payload
});
var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
} else {
var authorizationUrl = service.authorize();
Logger.log('Open the following URL and re-run the script: %s',
authorizationUrl);
}
}
function doGet() {
return HtmlService.createHtmlOutput(ScriptApp.getService().getUrl());
}
/**
* Reset the authorization state, so that it can be re-tested.
*/
function reset() {
var service = getService();
service.reset();
}
/**
* Configures the service.
*/
function getService() {
return OAuth1.createService('Twitter')
// Set the endpoint URLs.
.setAccessTokenUrl('https://api.twitter.com/oauth/access_token')
.setRequestTokenUrl('https://api.twitter.com/oauth/request_token')
.setAuthorizationUrl('https://api.twitter.com/oauth/authorize')
// Set the consumer key and secret.
.setConsumerKey(CONSUMER_KEY)
.setConsumerSecret(CONSUMER_SECRET)
// Set your user's access token key and secret
.setAccessToken(TOKEN, TOKEN_SECRET)
.setCallbackFunction('authCallback')
}
/**
* Handles the OAuth callback.
*/
function authCallback(request) {
var service = getService();
var authorized = service.handleCallback(request);
if (authorized) {
return HtmlService.createHtmlOutput('Success!');
} else {
return HtmlService.createHtmlOutput('Denied');
}
}
Alternatively, you can use Google's own OAuth 1 replacement script to sign OAuth 1 requests. You can find an example of usage in the Google Ads script page.
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 using this code in google script from request to google fusion tables
https://developers.google.com/fusiontables/docs/samples/apps_script
function getGAauthenticationToken(email, password) {
password = encodeURIComponent(password);
var response = UrlFetchApp.fetch("https://www.google.com/accounts/ClientLogin", {
method: "post",
payload: "accountType=GOOGLE&Email=" + email + "&Passwd=" + password + "&service=fusiontables&Source=testing"
});
var responseStr = response.getContentText();
responseStr = responseStr.slice(responseStr.search("Auth=") + 5, responseStr.length);
responseStr = responseStr.replace(/\n/g, "");
return responseStr;
}
function getdata(authToken) {
query = encodeURIComponent("SHOW TABLES");
var URL = "http://www.google.com/fusiontables/api/query?sql=" + query;
var response = UrlFetchApp.fetch(URL, {
method: "get",
headers: {
"Authorization": "GoogleLogin auth=" + authToken,
}
});
return response.getContentText();
}
function test(){
var email = "xyz#gmail.com";
var pass = "xyz";
var token = getGAauthenticationToken(email,pass);
Logger.log(getdata(token));
}
but, how I can make the connection with OAuth 2.0 without user/pass ?
Not oAuth 2.0, Apps Script only supports 1.0 yet. But you can use 1.0 normally with the Fusion Tables API. There's no need for user-pass info. Here's a function I wrote a long time ago to set oAuth om my UrlFetch requests to Google APIs.
/**
* Set up Google's oAuth authentication for UrlFetch
* #retuns {Object} args to be used UrlFetchApp
* #param {string} name oAuth service name, can be anything
* but must not repeat between different scopes
* recommend to use a meaninful name related to the scope
* #param {string} scope google scope for oAuth
*/
function googleOAuth(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
There's also a notable library now, linked on Google Apps Script site, that will automate even more things to you. Please take a look.