Author: By Raj
Part of our Google Apps Script Consulting guides. Need this built for your team? Hire a Google Apps Script developer.
Estimated reading time: 10 minutes
Using Service Accounts in Google Apps Script for Server-to-Server Auth
Service accounts let server-style code act without a human clicking authorize, critical for nightly ETL and signing JWTs to Google APIs or third parties. In Apps Script, patterns differ from Cloud Run but the crypto is the same.
Domain-wide delegation allows a service account to impersonate Workspace users for Gmail or Drive access, powerful and sensitive. Store private keys in Script Properties or, preferably, pass short-lived tokens from a secure vault.
This article explains when Apps Script alone suffices versus when to keep keys only on Cloud Run. Cross-read /blog/apps-script-oauth2-guide for user-delegated OAuth flows.
Service account fundamentals
Create the account in Google Cloud Console, download JSON keys once, and restrict IAM roles to the minimum API scopes. Rotate keys on a calendar schedule.
Apps Script can sign JWTs with Utilities.computeRsaSha256Signature when you paste the key material into Script Properties, acceptable only for low-risk internal tools.
Domain-wide delegation
Workspace super admins authorize the client ID with explicit OAuth scopes in Admin Console. Without delegation, service accounts cannot read user mailboxes.
Audit which scripts impersonate whom. Prefer group aliases and shared drives when possible to reduce personal mailbox access.
JWT bearer token exchange
Build a JWT with iss (client email), scope, aud (token endpoint), and exp (~1 hour). Exchange it for an access_token via UrlFetchApp.post to oauth2.googleapis.com/token.
Cache access tokens in CacheService or Script Properties with expiry timestamps to avoid signing every fetch.
When not to put keys in Script
Regulated environments should keep private keys on Cloud Run with Secret Manager; Apps Script calls HTTPS endpoints you control.
User OAuth via the OAuth2 library is simpler for SaaS APIs like HubSpot when a human can authorize once, see /blog/apps-script-hubspot-integration.
Example code
function getServiceAccountToken() {
const props = PropertiesService.getScriptProperties();
const clientEmail = props.getProperty('SA_EMAIL');
const privateKey = props.getProperty('SA_PRIVATE_KEY').replace(/\\n/g, '\n');
const now = Math.floor(Date.now() / 1000);
const header = Utilities.base64EncodeWebSafe(JSON.stringify({ alg: 'RS256', typ: 'JWT' }));
const claim = Utilities.base64EncodeWebSafe(JSON.stringify({
iss: clientEmail,
scope: 'https://www.googleapis.com/auth/spreadsheets',
aud: 'https://oauth2.googleapis.com/token',
exp: now + 3600,
iat: now,
}));
const sig = Utilities.computeRsaSha256Signature(header + '.' + claim, privateKey);
const jwt = header + '.' + claim + '.' + Utilities.base64EncodeWebSafe(sig);
const res = UrlFetchApp.fetch('https://oauth2.googleapis.com/token', {
method: 'post',
payload: { grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion: jwt },
});
return JSON.parse(res.getContentText()).access_token;
}| Approach | Best for | Tradeoff |
|---|---|---|
| Apps Script native | Google Workspace-centric workflows | 6-min limit, quotas |
| Zapier / Make | No-code, many connectors | Per-task cost, vendor lock-in |
| Python + Cloud | Heavy data / ML | Hosting cost, separate auth |
| Google Apps Script consulting | Production custom logic | Build cost, you own code |
FAQ
Can Apps Script use default compute credentials?
No. Apps Script projects are not GCP VMs. You must supply explicit credentials via JWT, OAuth user flow, or call a middle-tier you host.
Is storing a private key in Script Properties safe?
Only editors of the script project can read properties, but anyone with edit access is trusted. For stricter controls, keep keys off-Workspace in Secret Manager.
What scopes are needed for Sheets-only ETL?
Often https://www.googleapis.com/auth/spreadsheets or drive.file if using picker-based access. Avoid https://mail.google.com/ unless mail access is essential.
How does delegation differ from shared drives?
Shared drives grant group access without impersonation. Delegation lets code act as user@company.com, use only when business logic requires personal Drive paths.
Can service accounts send Gmail?
With domain-wide delegation and Gmail API scopes, yes, but many teams instead use MailApp as the installing user for simpler audit trails.
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 Using Service Accounts in Google Apps Script for Server-to-Server Auth script template
I'll email you a production-ready, commented version you can deploy in 10 minutes.
Continue reading
Apps Script Core
How to Automate Google Sheets with Apps Script (Beginner Guide)
Apps Script Core
Master Google Apps Script: A Step-by-Step Roadmap for Non-Coders
Apps Script Core
Google Apps Script Trigger Not Working? Here's the Fix
From another topic
Google Sheets CRM Automation: Triggers, Pipelines, and Follow-Ups →Need help with this? I handle this as part of my Google Apps Script Consulting service.
Workflow automation, script audits, triggers, quotas, and production best practices.
See how it works →