Why
The product wants Google sign-in on /login and /signup. The frontend side is implemented behind an honesty gate (ui GoogleSignInButton): the button renders only when VITE_GOOGLE_OAUTH_CLIENT_ID is configured AND the account client implements the exchange — so nothing user-visible exists until this endpoint does.
The current identity API (spec bef4de6) has no social/OAuth surface; identity is email+password with email verification.
Proposed contract
POST /api/v1/auth/oauth/google — 공개, 200
Request:
{ "idToken": "(Google ID token JWT from Google Identity Services)", "deviceLabel": "Web browser" }
Response: identical to LoginResponse — accountId, sessionId, sessionToken, expiresAt — so the session semantics (rotation, logout, expiry) stay one system.
Server responsibilities:
- Verify the ID token signature against Google JWKS,
aud = our OAuth client id, iss = accounts.google.com, exp.
- Require
email_verified: true; treat Google-verified email as satisfying our email-verification step.
- First sight of a Google subject: create the account (email from token), record the social identity linkage (new table, forward-only migration); afterwards: log the linked account in.
- Same session issuance path as password login (session token, expiry, device label).
- 401 with a stable code (e.g.
GOOGLE_TOKEN_REJECTED) for invalid/expired tokens; correlation id as elsewhere.
Notes
- This is an identity-domain (A) product change: account provisioning without a password touches
db/schema.dbml (identity tables) and possibly identity specs — flagging rather than implementing past the authority gate.
- Frontend reference: ui
src/api/account.ts loginWithGoogle, src/components/GoogleSignInButton.tsx.
🤖 Generated with Claude Code
Why
The product wants Google sign-in on /login and /signup. The frontend side is implemented behind an honesty gate (ui
GoogleSignInButton): the button renders only whenVITE_GOOGLE_OAUTH_CLIENT_IDis configured AND the account client implements the exchange — so nothing user-visible exists until this endpoint does.The current identity API (spec bef4de6) has no social/OAuth surface; identity is email+password with email verification.
Proposed contract
POST /api/v1/auth/oauth/google— 공개, 200Request:
{ "idToken": "(Google ID token JWT from Google Identity Services)", "deviceLabel": "Web browser" }Response: identical to
LoginResponse—accountId,sessionId,sessionToken,expiresAt— so the session semantics (rotation, logout, expiry) stay one system.Server responsibilities:
aud= our OAuth client id,iss= accounts.google.com,exp.email_verified: true; treat Google-verified email as satisfying our email-verification step.GOOGLE_TOKEN_REJECTED) for invalid/expired tokens; correlation id as elsewhere.Notes
db/schema.dbml(identity tables) and possibly identity specs — flagging rather than implementing past the authority gate.src/api/account.tsloginWithGoogle,src/components/GoogleSignInButton.tsx.🤖 Generated with Claude Code