Google OAuth Provider¶
Implements OAuthAuthorizationServerProvider from the MCP SDK, delegating identity verification to Google while owning the full OAuth 2.1 state machine.
Overview¶
The provider handles:
- Dynamic Client Registration — MCP clients register themselves on first connection.
- Authorization — Redirects clients to Google's authorization endpoint; stores pending auth state in GCS.
- Google callback — Exchanges the Google code for a userinfo token, verifies the email, and mints an MCP authorization code.
- Token exchange — Exchanges MCP authorization codes for access/refresh token pairs.
- Token refresh — Issues new access tokens from valid refresh tokens.
- Token revocation — Removes both the access token and all associated refresh tokens (or vice versa).
State persistence¶
All OAuth state is stored in a single JSON blob at oauth-state/state.json in the GCS bucket configured by OAUTH_STATE_BUCKET. The blob is read at startup and written synchronously after every mutation. This ensures sessions survive Cloud Run container restarts and scale-to-zero events.
The blob contains:
{
"clients": { "<client_id>": { ... } },
"auth_codes": { "<code>": { ... } },
"access_tokens": { "<token>": { ... } },
"refresh_tokens": { "<token>": { ... } },
"pending_auths": { "<google_state>": { ... } }
}
Expired tokens are filtered out on load and never written back.
Token lifetimes¶
| Token | TTL |
|---|---|
| Access token | 3,600 s (1 hour) |
| Refresh token | 2,592,000 s (30 days) |
| Authorization code | 300 s (5 minutes) |
| Pending auth state | 600 s (10 minutes) |
Module reference¶
the_curator.auth.provider
¶
Google OAuth 2.0 delegation provider for the MCP authorization server.
Implements OAuthAuthorizationServerProvider so the MCP SDK handles all protocol-level OAuth 2.1 machinery. Identity verification is delegated to Google; only the configured allowed_email can authenticate.
State is persisted to a GCS blob so tokens survive Cloud Run restarts.
logger = logging.getLogger(__name__)
module-attribute
¶
GOOGLE_AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth'
module-attribute
¶
GOOGLE_TOKEN_URL = 'https://oauth2.googleapis.com/token'
module-attribute
¶
GOOGLE_USERINFO_URL = 'https://www.googleapis.com/oauth2/v3/userinfo'
module-attribute
¶
ACCESS_TOKEN_TTL = 3600
module-attribute
¶
REFRESH_TOKEN_TTL = 86400 * 30
module-attribute
¶
AUTH_CODE_TTL = 300
module-attribute
¶
STATE_BLOB_NAME = 'oauth-state/state.json'
module-attribute
¶
GoogleOAuthProvider
¶
OAuth provider that delegates identity verification to Google.
Single-user: only allowed_email can authenticate. All OAuth state is kept in memory and persisted to GCS after every mutation so container restarts don't invalidate active sessions.
__init__(google_client_id: str, google_client_secret: str, allowed_email: str, server_url: str, gcs_bucket: str) -> None
¶
get_client(client_id: str) -> OAuthClientInformationFull | None
async
¶
register_client(client_info: OAuthClientInformationFull) -> None
async
¶
authorize(client: OAuthClientInformationFull, params: AuthorizationParams) -> str
async
¶
handle_google_callback(code: str, state: str) -> str
async
¶
Exchange Google code for identity, verify email, mint MCP auth code.
Returns the redirect URL to send the browser back to the MCP client. Raises ValueError if state is invalid or the user is not authorized.