Skip to content

Instantly share code, notes, and snippets.

@tanaikech
Last active June 22, 2024 02:21
Show Gist options
  • Save tanaikech/20ea127a8e23a7c609f8d764c8b7ed7c to your computer and use it in GitHub Desktop.
Save tanaikech/20ea127a8e23a7c609f8d764c8b7ed7c to your computer and use it in GitHub Desktop.
Retrieving Access Token for Service Account using Google Apps Script

Retrieving Access Token for Service Account using Google Apps Script

Updated on June 22, 2024

This is a sample script for retrieving the access token for Service Account using Google Apps Script. The flow for using this script is as follows.

Usage

  1. Create the Service Account and retrieve JSON file.
  2. Put Scopes, private_key and client_email as an object.
  • If you want to use impersonate email, please set the value of impersonate_email.
  1. Run the script.
/**
 * ### Description
 * Get access token from service account.
 * ref: https://tanaikech.github.io/2018/12/07/retrieving-access-token-for-service-account-using-google-apps-script/
 *
 * @param {Object} object Object including private_key, client_email, impersonate_email.
 * @param {String} object.private_key
 * @param {String} object.client_email
 * @param {String} object.impersonate_email
 * @param {Array} object.scopes
 * @returns {String} Access token.
 */
function getAccessTokenFromServiceAccount_(object) {
  const { private_key, client_email, impersonate_email = "", scopes = [] } = object;
  const url = "https://www.googleapis.com/oauth2/v4/token";
  const header = { alg: "RS256", typ: "JWT" };
  const now = Math.floor(Date.now() / 1000);
  const claim = { iss: client_email, scope: scopes.join(" "), aud: url, exp: (now + 3600).toString(), iat: now.toString() };
  if (impersonate_email != "") {
    claim.sub = impersonate_email;
  }
  const signature = Utilities.base64Encode(JSON.stringify(header)) + "." + Utilities.base64Encode(JSON.stringify(claim));
  const jwt = signature + "." + Utilities.base64Encode(Utilities.computeRsaSha256Signature(signature, private_key));
  const params = { payload: { assertion: jwt, grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer" } };
  const res = UrlFetchApp.fetch(url, params);
  const { access_token } = JSON.parse(res.getContentText());
  return access_token;
}


// Please run this script.
function main() {
  const object = {
    private_key: "-----BEGIN PRIVATE KEY-----\n###-----END PRIVATE KEY-----\n",
    client_email: "###",
    // impersonate_email: "###", // If you want to use an impersonate email, please set this.
    scopes: ["###", "###",,,],
  };
  const accessToken = getAccessTokenFromServiceAccount_(object);
  console.log(accessToken);
}

Sample script

When you can obtain the access token by the above script, you can also use the following sample script. The following sample script retrieves the file list of the drive of the service account with Method: files.list of Drive API v3.

function sample() {
  const object = {
    private_key: "-----BEGIN PRIVATE KEY-----\n###-----END PRIVATE KEY-----\n",
    client_email: "###",
    // impersonate_email: "###", // If you want to use an impersonate email, please set this.
    scopes: ["https://www.googleapis.com/auth/drive.metadata.readonly"],
  };
  const accessToken = getAccessTokenFromServiceAccount_(object);

  const url = `https://www.googleapis.com/drive/v3/files?access_token=${accessToken}`;
  const res = UrlFetchApp.fetch(url);
  console.log(res.getContentText());
}

References

@deniscanevaro
Copy link

Excelente

@majestique
Copy link

The url is updated to v4 now: https://www.googleapis.com/oauth2/v4/token
If you need to impersonate email (for scoped/secured access) you'll need:

var claim = {
  iss: client_email,
  sub:  "yourimpersonate@email.com",
  scope: scopes.join(" "),
  aud: url,
  exp: (now + 3600).toString(),
  iat: now.toString(),
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment