2
votes

Trying to access a google cloud datastore from google apps script with a service account like this. I have got the sample from here I am not sure if the SCOPE is ok or if another scope is needed. Running the function run() gives errors like "Error retrieving token: invalid_scope, https://www.googleapis.com/auth/userinfo.email is not a valid audience string."

// testing Cloud Datastore access via service account
var PRIVATE_KEY = "-----BEGIN PRIVATE KEY----------END PRIVATE KEY-----\n";
var CLIENT_EMAIL = "[email protected]";
var USER_EMAIL = "[email protected]";
var CLIENT_ID = "104548139575444821912";
var SCOPE = "https://www.googleapis.com/auth/datastore/v1"; 

/**
 * Authorizes and makes a request to the Cloud Datastore 
 */
function run() {
  var service = getService();
  if (service.hasAccess()) {
    var url = SCOPE;
    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());
  }
}

/**
 * Reset the authorization state, so that it can be re-tested.
 */
function reset() {
  getService().reset();
}

/**
 * Configures the service.
 */
function getService() {
  return OAuth2.createService('CloudDatastore:' + USER_EMAIL)
      // Set the endpoint URL.
      .setTokenUrl('https://accounts.google.com/o/oauth2/token')

      // Set the private key and issuer.
      .setPrivateKey(PRIVATE_KEY)
      .setIssuer(CLIENT_EMAIL)
      // .setClientId(CLIENT_ID)

      // 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/userinfo.email https://www.googleapis.com/auth/datastore/v1');
}
1

1 Answers

2
votes

ever tried not requesting that scope, which is not stated in the example, at all? request scope https://www.googleapis.com/auth/datastore. while that GoogleDrive example has PRIVATE_KEY, CLIENT_EMAIL,USER_EMAIL (the PK and email address of the service account need to be assigned)... while it states, that:

// 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)

if your account is neither for work (GSuite) nor educational, you'll not be able to impersonate the service account; which leaves you with two options: a) do not attempt to impersonate anybody with the service account, or b) create a GSuite domain with domain-wide delegation. one obviously cannot do that on a domain alike gmail.com, delegating off-domain accounts also won't work out; in case it is a GSuite domain, see domain-wide delegation.

ever tried to var SCOPES="https://www.googleapis.com/auth/cloud-platform, https://www.googleapis.com/auth/datastore"; and then.setScope(SCOPES)? requesting an invalid_scope won't lead nowhere, which means either invalid or the delegation had not been configured. it states, that

This must match one of the scopes configured during the setup of domain-wide delegation.

Perform G Suite Domain-Wide Delegation of Authority explain it. domain-wide delegations needs to be enabled when creating the service account - and then accordingly delegated in the Admin Console. OAuth2ServiceAccount is the ID protocol.

Screenshot 01

under Advanced settings > Authentication > Manage API client access, there needs to be the email address of the service account added with the according API scope (that error message is just there from the previous input, both scopes might be required there): Screenshot 02

on the Cloud Console, it is about the same: Screenshot 03

see the API documentation first. once connected, see the console.

added an example for rest/v1/projects (one can build/test the requests there, too) to my GitHub:

see CloudDatastore.gs (it loads the configuration .json from Google Drive).