Google Authentication for Node.js & Python
Libraries
Node.js
google-auth-library— core auth library (OAuth2Client, GoogleAuth, JWT, Compute, Impersonated)googleapis— Google API client (wraps google-auth-library)
npm install google-auth-library
npm install googleapis
The client.fetch() calls below require google-auth-library ≥ 10.1.0 (the
fetch-compatible API landed in 10.1.0, 2025-06-12); on 9.x use
client.request() with the same arguments. Checked 2026-08-31: latest is 11.x
and keeps both methods.
Python
google-auth— core auth library (google.oauth2, google.auth, credentials, transport)google-auth-oauthlib— OAuth 2.0 user-credential flow helpers (Flow, InstalledAppFlow)google-api-python-client— Google API client (wraps google-auth)
pip install google-auth
pip install google-auth-oauthlib
pip install google-api-python-client
Authentication Methods Overview
| Method | Use Case | Node.js Key Class | Python Key Module / Class |
|---|---|---|---|
| ADC | Same identity for all users, server-to-server | GoogleAuth |
google.auth.default() |
| OAuth 2.0 | Actions on behalf of end users | OAuth2Client |
google_auth_oauthlib.flow.Flow |
| Sign In with Google (GIS) | User sign-in/sign-up on websites — the google-signin skill's ground | GIS JS SDK + verifyIdToken() |
GIS JS SDK + id_token.verify_oauth2_token() |
| JWT / Service Account | Server-to-server, single identity | JWT |
service_account.Credentials |
| API Key | Public data, no user context | OAuth2Client({ apiKey }) |
passed to googleapiclient.discovery.build(developerKey=) |
| Compute | On GCP with attached service account | Compute |
google.auth.compute_engine.Credentials |
| Workload Identity Federation | AWS/Azure/OIDC → GCP without SA keys | ExternalAccountClient |
google.auth.identity_pool.Credentials / google.auth.aws.Credentials |
Quick Patterns
1. Application Default Credentials (ADC)
Node.js
const {GoogleAuth} = require('google-auth-library');
const auth = new GoogleAuth({
scopes: 'https://www.googleapis.com/auth/cloud-platform'
});
const client = await auth.getClient();
const res = await client.fetch('https://dns.googleapis.com/dns/v1/projects/...');
Python
import google.auth
import google.auth.transport.requests
credentials, project = google.auth.default(
scopes=['https://www.googleapis.com/auth/cloud-platform']
)
request = google.auth.transport.requests.Request()
credentials.refresh(request)
ADC search order (env var FIRST — this line was reversed): GOOGLE_APPLICATION_CREDENTIALS env var → gcloud auth application-default login file → attached service account (metadata). Print the RESOLVED principal and source (no secret) before configuring — with more than one present, only the resolved source names which you are actually using.
For detailed ADC setup and service account usage, see references/adc-and-service-accounts.md.
2. OAuth 2.0 Web Server Flow
Node.js
const {OAuth2Client} = require('google-auth-library');
const client = new OAuth2Client({
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
redirectUri: REDIRECT_URI
});
const authUrl = client.generateAuthUrl({
access_type: 'offline',
scope: ['https://www.googleapis.com/auth/userinfo.profile'],
state: crypto.randomBytes(32).toString('hex'),
include_granted_scopes: true
});
// After redirect: exchange code for tokens
const {tokens} = await client.getToken(code);
client.setCredentials(tokens);
Python
from google_auth_oauthlib.flow import Flow
flow = Flow.from_client_secrets_file(
'client_secret.json',
scopes=['https://www.googleapis.com/auth/userinfo.profile'],
redirect_uri=REDIRECT_URI
)
authorization_url, state = flow.authorization_url(
access_type='offline',
include_granted_scopes='true'
)
# After redirect: exchange code for tokens
flow.fetch_token(code=code)
credentials = flow.credentials
refresh_token is only returned on the first authorization. Use prompt: 'consent' (Node.js) or prompt='consent' (Python) to force re-consent.
For the complete OAuth 2.0 flow (parameters, token exchange, refresh, revocation, incremental auth), see references/oauth2-web-server.md.
3. Verifying a Google ID Token — the library call
Node.js
const {OAuth2Client} = require('google-auth-library');
const client = new OAuth2Client();
const ticket = await client.verifyIdToken({
idToken: token,
audience: WEB_CLIENT_ID,
});
const payload = ticket.getPayload();
Python
from google.oauth2 import id_token
from google.auth.transport import requests
payload = id_token.verify_oauth2_token(token, requests.Request(), WEB_CLIENT_ID)
The call checks signature, aud, exp and iss — and nothing else. That is
the library contract, not the web sign-in contract: for the sign-in security
checklist (nonce binding, email_verified, login-CSRF defense, account
linking) use the google-signin skill — it is the one home for that contract,
and this skill deliberately does not restate it.
4. JWT / Service Account
Node.js
const {JWT} = require('google-auth-library');
const keys = require('./service-account-key.json');
const client = new JWT({
email: keys.client_email,
key: keys.private_key,
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
});
const res = await client.fetch(url);
Python
from google.oauth2 import service_account
credentials = service_account.Credentials.from_service_account_file(
'service-account-key.json',
scopes=['https://www.googleapis.com/auth/cloud-platform']
)
# Or from a dict already loaded into memory:
credentials = service_account.Credentials.from_service_account_info(
info,
scopes=['https://www.googleapis.com/auth/cloud-platform']
)
5. API Key
Node.js
const {OAuth2Client} = require('google-auth-library');
const client = new OAuth2Client({ apiKey: 'my-api-key' });
// Or via GoogleAuth:
const {GoogleAuth} = require('google-auth-library');
const auth = new GoogleAuth({
clientOptions: { apiKey: 'my-api-key' }
});
Python
from googleapiclient.discovery import build
service = build('customsearch', 'v1', developerKey='my-api-key')
6. Token Refresh
Node.js
client.on('tokens', (tokens) => {
if (tokens.refresh_token) {
// Store refresh_token — only sent on first auth
}
console.log(tokens.access_token);
});
Python
from google.auth.transport.requests import Request
if credentials.expired and credentials.refresh_token:
credentials.refresh(Request())
# credentials.token is the new access token
# credentials.expiry is the new expiration datetime
Security Best Practices
- Never expose
client_secretor service account keys in client-side code - Always validate
stateparameter to prevent CSRF in OAuth flows - Use
sub(notemail) as the unique user identifier from Google ID tokens - Store
refresh_tokensecurely; it's only returned on first authorization - Validate external credential configurations before use (check
token_url,service_account_impersonation_urlpoint to googleapis.com) - Prefer Workload Identity Federation over service account keys for non-GCP environments
- For end-user web sign-in, apply the google-signin skill's full checklist — a partial restatement here is how the two skills drifted apart once already
- Fail closed on a missing production secret. The session signing secret, and any credential-store key, is REQUIRED in production with NO dev fallback — a hardcoded default signs every deployment's cookies with a key that lives in the repo. Missing → refuse to boot, never a warning-and-continue (DV-07).
- Logs are sanitized; a credential never reaches one. No token, no
client_secret, norefresh_token, no session value in a log line, a stack trace, or an error message — a token in a log is a token anyone with log access holds. Redact by allow-list, not by trying to strip the secret out. - HTTPS is mandatory and the credential store can fail. The auth cookie is
Secureand the callback refuses plain HTTP (an OAuth code overhttp://is a code on the wire); and a credential-store read/write that FAILS is an auth failure — re-prompt or 503, never proceed as if the credentials loaded. - Python-specific: reuse a single
google.auth.transport.requests.Request()instance across verifications for connection pooling; do not create a new one per call in hot paths
Reference Files
- OAuth 2.0 Web Server Flow — Complete OAuth 2.0 flow: parameters, consent, token exchange, refresh, revocation, incremental auth, error handling (Node.js + Python)
- ADC & Service Accounts — Application Default Credentials setup, service account keys, JWT, Compute credentials, environment configuration (Node.js + Python)
- Sign In with Google — Google Identity Services (GIS), ID token verification, CSRF protection, One Tap, FedCM (Node.js + Python)
- Workload Identity Federation — AWS, Azure, OIDC/SAML federation, workforce identity, executable-sourced credentials (Node.js + Python)