# Google OAUTH

> Google OAuth Skill

- Skill: `utxo-ag/google-oauth` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add utxo-ag/google-oauth`
- Raw SKILL.md: https://api.skillmd.com/api/skills/utxo-ag/google-oauth/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: utxo-AG (https://skillmd.com/u/utxo-ag)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/utxo-ag/google-oauth

---

# Google OAuth Skill

Authenticate users with Google APIs via OAuth 2.0 to access services like Gmail, Analytics, Drive, Calendar, Sheets, and more.

## Prerequisites

- `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` environment variables must be set
- `REDIRECT_URI` environment variable must be set (e.g. in `.env`). This must match the authorized redirect URI configured in the Google Cloud Console.
- Node.js must be available

## Scope Reference

| Service | Scope key | Full scope | Use when |
|---------|-----------|-----------|----------|
| Analytics (read) | `analytics.readonly` | `https://www.googleapis.com/auth/analytics.readonly` | viewing reports, properties, metrics |
| Gmail (read) | `gmail.readonly` | `https://www.googleapis.com/auth/gmail.readonly` | reading emails |
| Gmail (send) | `gmail.send` | `https://www.googleapis.com/auth/gmail.send` | sending emails |
| Gmail (full) | `gmail.modify` | `https://www.googleapis.com/auth/gmail.modify` | read + write + delete |
| Drive (read) | `drive.readonly` | `https://www.googleapis.com/auth/drive.readonly` | listing/reading files |
| Drive (full) | `drive.file` | `https://www.googleapis.com/auth/drive.file` | creating/editing files |
| Calendar (read) | `calendar.readonly` | `https://www.googleapis.com/auth/calendar.readonly` | viewing events |
| Calendar (write) | `calendar.events` | `https://www.googleapis.com/auth/calendar.events` | creating/editing events |
| Sheets | `spreadsheets` | `https://www.googleapis.com/auth/spreadsheets` | reading/writing spreadsheets |

## Instructions

When the user asks to interact with a Google service, follow these steps:

### Step 1: Identify the scope

Map the user's request to the minimal scope from the table above. Always prefer read-only scopes unless write access is explicitly needed.

### Step 2: Check for an existing token

```bash
node ~/.claude/skills/google-oauth/scripts/token-store.js check <scope_key>
```

If exit code is 0 (token is valid), skip to Step 5.

### Step 3: Start the callback server

**Before proceeding**, verify that `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, and `REDIRECT_URI` are all set. If any are missing, **stop** and tell the user which variables need to be set in the `.env` file before authenticating.

Generate a random state value and start the server in the background:

```bash
STATE=$(node -e "console.log(require('crypto').randomBytes(16).toString('hex'))")
node ~/.claude/skills/google-oauth/scripts/oauth-callback-server.js 9876 "$STATE" "$REDIRECT_URI" &
OAUTH_PID=$!
```

Wait briefly for the server to start, then verify it printed `LISTENING`.

### Step 4: Present the authorization URL

Construct the URL using the `GOOGLE_CLIENT_ID` env var and the chosen scope:

```
https://accounts.google.com/o/oauth2/v2/auth?client_id=${GOOGLE_CLIENT_ID}&redirect_uri=${REDIRECT_URI}&scope=https://www.googleapis.com/auth/SCOPE_KEY&response_type=code&access_type=offline&prompt=consent&state=${STATE}
```

Tell the user:
> Please open this link to authorize access: [the URL]
>
> After you authorize in your browser, the token will be captured automatically.

Then wait for the background server to complete. Check that stdout contains `TOKEN_RECEIVED`. If the server exits with an error or times out, inform the user and suggest retrying.

### Step 5: Use the token

Retrieve the access token:

```bash
TOKEN=$(node ~/.claude/skills/google-oauth/scripts/token-store.js get <scope_key>)
```

Use the token in API calls via curl with the `Authorization: Bearer $TOKEN` header. For example:

```bash
# Google Analytics — list accounts
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://analyticsadmin.googleapis.com/v1beta/accounts"

# Gmail — list messages
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://gmail.googleapis.com/gmail/v1/users/me/messages?maxResults=10"

# Drive — list files
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/drive/v3/files?pageSize=10"
```

### Token refresh

The `get` command in token-store.js automatically refreshes expired tokens using the stored refresh_token. If refresh fails (e.g., token was revoked), repeat Steps 3-4 to re-authorize.

