feat(auth): Sign in with Google (identity-only) on login #4083
Cross-repo impact
See what breaks downstream if this PR merges.
⮌ Merged
This pull request was merged into main.
c comment · e edit title · m merge · a approve · r request changes · ? shortcuts
Originally written by @ccantynz-alt on GitHub.
Imported from https://github.com/ccantynz-alt/AlecRae.com/pull/48
What
Adds a "Sign in with Google" option to the login page. This is identity-only (OpenID Connect:
openid/email/profile) and is deliberately separate from the existing Gmail mailbox connection (which uses the fullgmail.*scopes to read/send a user's mail). Passkey remains the hero auth method; Google sits underneath as a quieter secondary option.Why
~90% of the Gmail/Outlook users we're converting already have a Google account. A one-tap sign-in removes the biggest signup-friction point for exactly that audience — without making Google the face of our login, and without any competitive cost (their mail never routes through Google; this is purely identity).
Changes
API
GET /v1/auth/google— starts the flow (redirects to Google with an HMAC-signed CSRF state)GET /v1/auth/callback/google— exchanges the code, finds-or-creates the user (OAuth-only users get anullpassword hash), issues the standard token pair, and redirects to the web app with the access token in the URL fragment (kept out of logs/referrers)apps/api/src/lib/google-auth.ts— identity-only OAuth helper with its ownGOOGLE_AUTH_REDIRECT_URI(separate from the gmail-connectGOOGLE_REDIRECT_URI)apps/api/src/lib/oauth-state.ts—signAuthState/verifyAuthStatefor the unauthenticated sign-in flowWeb
/google/callbacklanding page that stores the session (mirrors login/register/passkey) and routes to the inboxConfig
GOOGLE_AUTH_REDIRECT_URIin.env.productionRequired setup in Google Cloud Console
Register both redirect URIs on the same OAuth client:
https://api.alecrae.com/v1/connect/callback/gmailhttps://api.alecrae.com/v1/auth/callback/googleVerification
bun run typecheck— API ✅ / web ✅bun run lint— 0 errors (pre-existingconsole.logwarnings only, none in new code)https://claude.ai/code/session_01McgJLnTbZG9mwhfwd5iAX3
Generated by Claude Code