Author: By Raj

Part of our Apps Script API Integrations guides. Need this built for your team? Hire a Google Apps Script developer.

Estimated reading time: 10 minutes

OAuth2 in Google Apps Script: Authenticate External APIs Step by Step

Third-party SaaS APIs often require OAuth2 authorization code or client credentials flows. Apps Script can host the callback in a web app doGet that writes tokens to Script Properties.

Use Google's OAuth2 Apps Script library for refresh tokens, or implement token exchange manually with UrlFetchApp.post to the provider token URL.

Contrast with service accounts in /blog/apps-script-service-account when no human login exists.

Authorization code flow overview

Step 1: Redirect user to provider authorize URL with client_id, scope, redirect_uri, state. Step 2: Provider redirects back with code. Step 3: Exchange code for access_token and refresh_token.

Store refresh_token encrypted-at-rest as Script Property limited to script editors.

Refreshing access tokens

Before each API call, check expiry timestamp in Properties. If expired, POST refresh_token grant and save new access_token.

Handle invalid_grant by emailing admin to re-authorize, user revoked app.

Callback web app deployment

Deploy doGet OAuth callback as Execute as: Me, accessible to users authorizing. Log state parameter match to prevent CSRF.

Register exact redirect URI in provider console, including /exec vs /dev.

Scope minimization

Request readonly CRM scopes if Sheets only ingests data. Re-authorize when adding write scopes, document for clients.

manifest appsscript.json oauthScopes must include external request scope plus script.container.ui if using HtmlService.

Example code

function exchangeCodeForToken(code) {
  const props = PropertiesService.getScriptProperties();
  const res = UrlFetchApp.fetch('https://provider.example/oauth/token', {
    method: 'post',
    payload: {
      grant_type: 'authorization_code',
      code: code,
      client_id: props.getProperty('CLIENT_ID'),
      client_secret: props.getProperty('CLIENT_SECRET'),
      redirect_uri: props.getProperty('REDIRECT_URI'),
    },
  });
  const tokens = JSON.parse(res.getContentText());
  props.setProperty('access_token', tokens.access_token);
  props.setProperty('refresh_token', tokens.refresh_token);
}
ApproachBest forTradeoff
Apps Script nativeGoogle Workspace-centric workflows6-min limit, quotas
Zapier / MakeNo-code, many connectorsPer-task cost, vendor lock-in
Python + CloudHeavy data / MLHosting cost, separate auth
API integration servicesProduction custom logicBuild cost, you own code

FAQ

Can I avoid a web app callback?

Some providers offer device code or long-lived private tokens, HubSpot private apps are an example. OAuth web app is standard for user data.

Where to store client secret?

Script Properties, never Sheet cells. Rotate if leaked.

Does Apps Script include OAuth for Google APIs?

Built-in for Google services when you enable advanced services. External APIs need manual token handling.

What is state parameter for?

Random string verified on callback to prevent cross-site request forgery during authorization.

HubSpot-specific steps?

See /blog/apps-script-hubspot-integration for CRM scopes and deal property pulls after OAuth completes.

Need this done for you? I handle this as part of my consulting work, fixed-price quote within 24 hours.

Book a call with Raj →

Get the full OAuth2 in Google Apps Script script template

I'll email you a production-ready, commented version you can deploy in 10 minutes.

Need help with this? I handle this as part of my Apps Script API Integrations service.

Shopify, Stripe, Slack, HubSpot, webhooks, and REST API connections.

See how it works →