Post

OAuth 2.0 with Google API's

OAuth 2.0 with Google API's

๐Ÿ” OAuth 2.0 with Google APIs โ€” From โ€œMagicโ€ to Mental Model โœจ

I recently went through a full OAuth 2.0 setup for a brand-new Google account, enabling Gmail, Drive, Docs, and Sheets API access.

Everything worked flawlessly โ€”
but it felt a bit like magic ๐Ÿช„

This post is my attempt to:

  • demystify what actually happened
  • explain why OAuth feels opaque the first time
  • show how developers usually avoid dealing with this more than once

๐Ÿงฑ The Setup (What I Actually Did)

โ˜๏ธ Google Cloud Console

  1. Created a new project
  2. Enabled APIs:
    • ๐Ÿ“ง Gmail API
    • ๐Ÿ“ Google Drive API
    • ๐Ÿ“ Google Docs API
    • ๐Ÿ“Š Google Sheets API
  3. Created an OAuth 2.0 Client ID (Desktop App)
  4. Configured the OAuth consent screen:
    • App name
    • External audience
    • Published to production
    • Scopes did not require verification โœ…
  5. Downloaded the OAuth client JSON

๐Ÿ” The OAuth Flow

  1. Used the client JSON to construct a consent URL
  2. Opened the URL and approved access
  3. Got redirected to http://localhost with an authorization code
  4. Exchanged the code for tokens
  5. Stored the refresh token
  6. Successfully accessed Gmail, Drive, Docs, and Sheets APIs ๐ŸŽ‰

Google now shows my app under Third-party connections, and I can revoke access at any time.


๐Ÿค” Why This Feels Like Magic

OAuth looks complex because:

  • ๐Ÿ”€ Redirects feel opaque
  • ๐Ÿ”‘ Tokens look scary
  • ๐Ÿ“š Everyone says โ€œjust use the SDKโ€
  • ๐Ÿงพ Docs explain what to do, not why

But underneath, OAuth 2.0 (Google flavor) is just:

  1. One GET request (consent)
  2. One redirect (authorization code)
  3. One POST request (token exchange)
  4. Saving a JSON file

Thatโ€™s it. No sorcery involved.


๐Ÿงญ OAuth Flow โ€” Visual Overview

flowchart LR
    A[๐Ÿ‘ค User opens Consent URL] --> B[๐Ÿ” Google Consent Screen]
    B -->|Allow| C[๐Ÿ” Redirect to localhost with code]
    C --> D[๐Ÿ“ฆ App exchanges code for tokens]
    D --> E[๐Ÿ”„ Refresh token stored]
    E --> F[๐Ÿ“ก API calls with access token]

From the downloaded client_secret.json, you already have:

  • client_id
  • auth_uri
  • redirect_uris

The consent URL is just:

1
2
3
4
5
6
7
https://accounts.google.com/o/oauth2/auth
  ?client_id=CLIENT_ID
  &redirect_uri=http://localhost
  &response_type=code
  &access_type=offline
  &prompt=consent
  &scope=SCOPE_1 SCOPE_2 ...

๐Ÿ“Œ Notes:

  • Scopes are space-separated
  • URL-encode spaces as %20
  • access_type=offline โ†’ refresh token
  • prompt=consent โ†’ force issuance

๐Ÿ“š Example Scopes

  • https://www.googleapis.com/auth/gmail.readonly
  • https://www.googleapis.com/auth/drive
  • https://www.googleapis.com/auth/documents
  • https://www.googleapis.com/auth/spreadsheets

Open the URL โ†’ click Allow โ†’ redirect happens.


๐Ÿ”„ Exchanging the Code for Tokens

After consent, the browser redirects to something like:

1
http://localhost/?code=4/0AbCdEfGhIj...

That code is exchanged for tokens via a simple HTTP POST:

1
2
3
4
5
6
curl -X POST https://oauth2.googleapis.com/token \
  -d client_id=CLIENT_ID \
  -d client_secret=CLIENT_SECRET \
  -d code=AUTH_CODE \
  -d grant_type=authorization_code \
  -d redirect_uri=http://localhost

Google responds with JSON:

1
2
3
4
5
6
7
{
  "access_token": "...",
  "expires_in": 3599,
  "refresh_token": "...",
  "scope": "...",
  "token_type": "Bearer"
}

โœจ This is the entire โ€œmagicโ€.


๐Ÿ† The Refresh Token Is the Real Prize

  • โฑ๏ธ Access tokens expire (~1 hour)
  • โ™ป๏ธ Refresh tokens live until:
    • user revokes access
    • app is deleted
    • consent is replaced

Refreshing later is just another POST:

1
2
3
4
5
curl -X POST https://oauth2.googleapis.com/token \
  -d client_id=CLIENT_ID \
  -d client_secret=CLIENT_SECRET \
  -d refresh_token=REFRESH_TOKEN \
  -d grant_type=refresh_token

No browser. No UI. No drama.


๐Ÿคฏ Do Developers Really Do This Every Time?

No. Absolutely not.

Hereโ€™s how reality looks.

1๏ธโƒฃ OAuth Is Done Once per Project

  • painful once
  • copy-pasted forever
  • never touched again unless scopes change

OAuth is treated like database migrations.


2๏ธโƒฃ SDKs Exist to Hide This

Libraries:

  • build URLs
  • start localhost listeners
  • parse redirects
  • store tokens

They donโ€™t change OAuth โ€” they just hide it.


3๏ธโƒฃ OAuth Is Centralized in Teams

In real systems:

  • one service handles OAuth
  • everyone else consumes tokens
  • most developers never see consent screens

OAuth becomes infrastructure, not app logic.


4๏ธโƒฃ Production Often Uses Service Accounts

For server-to-server access:

  • no browser
  • no user
  • no consent
  • no refresh tokens

Just signed JWTs and IAM roles ๐Ÿ”


๐Ÿง  Why Itโ€™s Still Worth Understanding

Even if you never do this manually again:

  • ๐Ÿ› ๏ธ Debugging OAuth failures gets easy
  • ๐Ÿ” Scope issues stop being mysterious
  • ๐Ÿšซ Revocation suddenly makes sense
  • ๐Ÿง‘โ€โš–๏ธ Security reviews stop being scary

Most importantly:

OAuth is not authentication.
OAuth is delegated API access encoded as JSON.

Once that clicks, the magic disappears.


โœจ Final Thoughts

OAuth feels complicated because it tries to solve:

  • trust
  • consent
  • revocation
  • least privilege
  • cross-app access

But the protocol itself is simple.

Do it once by hand and youโ€™ve seen behind the curtain ๐ŸŽญ
Next time, youโ€™ll happily let a tool do it for you ๐Ÿ˜„

This post is licensed under CC BY 4.0 by the author.