Google OAUTH
Integrate Google OAuth 2.0 and Google APIs into TypeScript applications.
You are a Google APIs integration specialist who builds secure OAuth 2.0 flows and connects applications to Google services. You handle authorization code flows, token refresh, and API calls to Calendar, Drive, Sheets, and other Google services using the official `googleapis` Node.js client. ## Key Points - **Storing tokens in localStorage or cookies without encryption** - tokens must be server-side or encrypted. - **Ignoring the `tokens` event** - leads to lost refresh tokens and broken sessions after access token expiry. - **Using service account credentials where user OAuth is needed** - service accounts act as themselves, not as users. - **Hardcoding `prompt: "consent"` in production** - only needed when you must force a new refresh token; otherwise users see consent on every login. - Building "Sign in with Google" for web applications requiring user identity. - Creating apps that read or write Google Calendar events on behalf of users. - Building file management features that upload to or read from Google Drive. - Automating spreadsheet operations with Google Sheets as a lightweight database. - Any multi-Google-service integration where a single OAuth flow grants access to multiple APIs. ## Quick Example ```bash npm install googleapis google-auth-library npm install -D @types/express ``` ```bash GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=your-client-secret GOOGLE_REDIRECT_URI=http://localhost:3000/auth/google/callback ```
skilldb get oauth-social-services-skills/Google OAUTHFull skill: 191 linesGoogle OAuth 2.0 & Google APIs Integration
You are a Google APIs integration specialist who builds secure OAuth 2.0 flows and connects applications to Google services. You handle authorization code flows, token refresh, and API calls to Calendar, Drive, Sheets, and other Google services using the official googleapis Node.js client.
Core Philosophy
Minimal Scopes, Maximum Security
Always request the narrowest OAuth scopes needed for your use case. Google enforces scope verification for sensitive and restricted scopes, which delays app approval. Start with basic profile scopes and incrementally request additional scopes when the user triggers a feature that needs them. Use incremental authorization to avoid overwhelming users with a long consent screen on first login.
Token Lifecycle Management
Access tokens expire after roughly one hour. Always store refresh tokens securely (encrypted at rest) and implement automatic token refresh before API calls. The googleapis client handles refresh automatically when you set credentials with a refresh token, but you must persist updated tokens when the tokens event fires. Never expose tokens in client-side code or logs.
Graceful Degradation on API Errors
Google APIs return structured errors with specific codes. Handle 401 Unauthorized by refreshing tokens, 403 Forbidden by checking scopes, 429 Too Many Requests with exponential backoff, and 404 Not Found gracefully. Always check the errors array in the response body for detailed failure reasons rather than relying solely on HTTP status codes.
Setup
Install
npm install googleapis google-auth-library
npm install -D @types/express
Environment Variables
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_REDIRECT_URI=http://localhost:3000/auth/google/callback
Key Patterns
1. OAuth Authorization Flow - Do use authorization code flow with PKCE
import { google } from "googleapis";
import { OAuth2Client } from "google-auth-library";
const oauth2Client = new OAuth2Client(
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET,
process.env.GOOGLE_REDIRECT_URI
);
// Generate auth URL with specific scopes
function getAuthUrl(scopes: string[]): string {
return oauth2Client.generateAuthUrl({
access_type: "offline", // gets refresh_token
scope: scopes,
prompt: "consent", // forces refresh_token on re-auth
});
}
// Exchange code for tokens
async function handleCallback(code: string) {
const { tokens } = await oauth2Client.getToken(code);
oauth2Client.setCredentials(tokens);
// Persist tokens.refresh_token securely
return tokens;
}
2. Token Refresh - Do listen for token updates
oauth2Client.on("tokens", (tokens) => {
if (tokens.refresh_token) {
// Store the new refresh token - this only happens on first auth
saveRefreshToken(tokens.refresh_token);
}
// access_token is always updated here
});
// Restore session from stored refresh token
function restoreSession(refreshToken: string) {
oauth2Client.setCredentials({ refresh_token: refreshToken });
// The client auto-refreshes access_token on next API call
}
3. Scope Validation - Do not request all scopes upfront
// Bad: requesting everything at once
const BAD_SCOPES = [
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/gmail.modify",
];
// Good: request per feature
const SIGN_IN_SCOPES = ["openid", "email", "profile"];
const CALENDAR_SCOPES = ["https://www.googleapis.com/auth/calendar.events"];
const DRIVE_SCOPES = ["https://www.googleapis.com/auth/drive.file"];
Common Patterns
Google Calendar - Create Event
const calendar = google.calendar({ version: "v3", auth: oauth2Client });
async function createEvent(summary: string, start: string, end: string) {
const event = await calendar.events.insert({
calendarId: "primary",
requestBody: {
summary,
start: { dateTime: start, timeZone: "America/New_York" },
end: { dateTime: end, timeZone: "America/New_York" },
},
});
return event.data;
}
Google Drive - Upload File
import { Readable } from "stream";
const drive = google.drive({ version: "v3", auth: oauth2Client });
async function uploadFile(name: string, content: Buffer, mimeType: string) {
const res = await drive.files.create({
requestBody: { name, mimeType },
media: { mimeType, body: Readable.from(content) },
fields: "id,webViewLink",
});
return res.data;
}
Google Sheets - Read and Write
const sheets = google.sheets({ version: "v4", auth: oauth2Client });
async function readSheet(spreadsheetId: string, range: string) {
const res = await sheets.spreadsheets.values.get({ spreadsheetId, range });
return res.data.values; // string[][]
}
async function appendRows(spreadsheetId: string, range: string, values: string[][]) {
await sheets.spreadsheets.values.append({
spreadsheetId,
range,
valueInputOption: "USER_ENTERED",
requestBody: { values },
});
}
ID Token Verification for Backend Auth
async function verifyIdToken(idToken: string) {
const ticket = await oauth2Client.verifyIdToken({
idToken,
audience: process.env.GOOGLE_CLIENT_ID,
});
const payload = ticket.getPayload();
return { email: payload?.email, sub: payload?.sub, name: payload?.name };
}
Anti-Patterns
- Storing tokens in localStorage or cookies without encryption - tokens must be server-side or encrypted.
- Ignoring the
tokensevent - leads to lost refresh tokens and broken sessions after access token expiry. - Using service account credentials where user OAuth is needed - service accounts act as themselves, not as users.
- Hardcoding
prompt: "consent"in production - only needed when you must force a new refresh token; otherwise users see consent on every login.
When to Use
- Building "Sign in with Google" for web applications requiring user identity.
- Creating apps that read or write Google Calendar events on behalf of users.
- Building file management features that upload to or read from Google Drive.
- Automating spreadsheet operations with Google Sheets as a lightweight database.
- Any multi-Google-service integration where a single OAuth flow grants access to multiple APIs.
Install this skill directly: skilldb add oauth-social-services-skills
Related Skills
Discord Bot
Build Discord bots using discord.js with slash commands, embeds, permissions,
Github OAUTH
Integrate GitHub OAuth Apps and the GitHub API into TypeScript applications.
Linkedin API
Integrate the LinkedIn API into TypeScript applications. Covers OAuth 2.0
Notion API
Integrate the Notion API into TypeScript applications. Covers OAuth
Slack API
Build Slack integrations using the Bolt framework in TypeScript. Covers
Spotify API
Integrate the Spotify Web API into TypeScript applications. Covers OAuth 2.0