Repository navigation
Setup Google OAuth
Blocks the Phase 1 Google path (T-1.5 onward), which is every student's sign-in and the only self-signup route (§6.3). There is no workaround: the authorization-code exchange needs a real client secret, and E2E 3 mocks the GIS widget, not the exchange.
Owner: Thuong. Verify with make verify-google when done.
§2 named Google Identity Services; §5.3 required Authorization Code + PKCE. Those are incompatible, so we do not use the GIS SDK.
Google's authorization server supports PKCE — its discovery document advertises
code_challenge_methods_supported: ["plain","S256"], and make verify-google
re-checks that every run. The GIS wrapper (initCodeClient) has no documented
way to pass a code_challenge. Thuong approved building the request directly.
So the flow is: generate a verifier, derive an S256 challenge, add state, open
Google's authorization_endpoint in a popup, and post
{ code, codeVerifier, redirectUri } to POST /auth/google. The client secret
never leaves the backend.
What this means for the console: the Authorized redirect URIs are the load-bearing setting. JavaScript origins are registered too, but nothing depends on them now.
https://console.cloud.google.com
Create one, or reuse an existing one. Name it quizzivy.
-
User type: External. Students are outside any Workspace org.
-
App name
Quizzivy, your support email, your developer contact email. -
Scopes:
openid,email,profile— and nothing else.This matters. Those three are Google's non-sensitive scopes, and apps that request only non-sensitive scopes do not go through OAuth verification review. Adding anything else (Drive, Classroom, Calendar) puts the app into "sensitive" or "restricted" territory and triggers a review that can take weeks. §5.3 needs
sub,email,email_verified,name,picture— all covered by these three.
Set the app to "In production", not "Testing".
In Testing status, only users you add by hand to the test-user list can sign in at all. With ~50 students that means maintaining an allowlist, and every new student is blocked until you remember to add them — a support burden that will land on you at the worst possible moment, in the middle of a test.
Because the app requests only non-sensitive scopes (step 2), publishing does not
require submitting for verification. The console tells you inline whether a
review is needed; if it offers to submit for verification, something other than
openid/email/profile crept into the scope list.
Unverified apps show an "unverified app" interstitial for sensitive scopes; with non-sensitive scopes only, students see the ordinary consent screen.
Credentials → Create credentials → OAuth client ID → Web application.
Name it quizzivy-web.
Authorized JavaScript origins — origins only, no path, no trailing slash:
http://localhost:5173
https://app.quizzivy.com
Authorized redirect URIs — full URLs:
http://localhost:5173/auth/google/callback
https://app.quizzivy.com/auth/google/callback
The redirect URIs are what matter (see O-13 above). The JavaScript origins are registered anyway — they cost nothing and keep the door open.
Replace app.quizzivy.com with the real host once O-01 is settled. Both must sit
under one registrable domain as the API — that is what makes the SameSite=Lax
refresh cookie work (docs/plan/00-overview.md §4.1).
VITE_GOOGLE_CLIENT_ID=<the client id>.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-<the secret>
GOOGLE_REDIRECT_URI=http://localhost:5173/auth/google/callback
.env is gitignored and must stay that way. The client ID is public and ships
in the frontend bundle (§5.3); the secret is backend-only and must never
reach web/, a commit, or this chat.
make verify-googleThis needs no browser and no consent screen. It POSTs a deliberately invalid authorization code to Google's token endpoint using your real credentials. Google validates the client before the code, so the error it returns identifies the problem exactly:
| Google's response | Meaning |
|---|---|
invalid_grant |
Pass. The credentials are correct; only the dummy code was rejected. |
invalid_client |
The client ID or secret is wrong. |
redirect_uri_mismatch |
GOOGLE_REDIRECT_URI is not registered on this client. |
- Verify the ID token properly:
iss,aud,exp, and the signature via JWKS athttps://www.googleapis.com/oauth2/v3/certs. Cache the JWKS and refetch on an unknownkid. -
email_verified: falseis rejected outright — no link, no create, even with a valid join code. This closes an account-takeover path and §5.1 states it without exception. - Google's
subis the stable identity; email can change.user_identitieskeys on(provider, provider_user_id)and storesemail_at_linkonly as a record of what it was.
Generated from docs/setup/google-oauth.md. Edit that file in the repository; changes made on this page are overwritten.
Generated from the repository's documentation on every push to develop.
Start here
Product
Implementation plan
- 00 Architecture overview
- 10 Phase 0: Scaffold and contract
- 11 Phase 1: Auth, join, shells
- 12 Phase 2: Admin authoring
- 13 Phase 3: Assign and take
- 14 Phase 4: Grade and results
- 15 Phase 5: Hardening
- 16 Phase 4.5: The student at a desk
- 17 Word import: milestone plan
- 18 Word import: teacher workflow
- 19 Versioned content contract
- 20 Data model
- 30 Risk register
- 40 Open items
- 50 Non-functional requirements
- 60 Backend architecture
- 91 September 2026 issue remediation
- 92 Student layouts and interaction rules
Redesign (Phase R)
- 70 Redesign overview
- 71 R1: Foundations (v0.7.0)
- 72 R2: Access (v0.8.0)
- 73 R3: Student console (v0.9.0)
- 74 R4: Teacher workspace (v0.10.0)
- 74d D4: Deck update (v0.11.0)
- 74e E1: Moving a question across a group
- 75 R5: Admin console and email (v0.12.0)
- 76 R6: Question types and scoring (v0.13.0)
- 77 R7: Collaboration (v0.14.0)
- 78 R8: Schedule (v0.15.0)
- 79 R9: Insights (v0.16.0)
- 80 R10: Learn (v0.17.0)
- 81 R11: Landing, leads, v1.0 (v1.0.0)
Setup and operations
- CI
- Deploying
- DNS for quizzivy.com
- Google OAuth client
- Production operations
- Cloudflare R2 bucket
- Word import worker
- R4 rehearsal on a Neon branch
Design
Team
- Agent team
- Verification environment
- Team ledger
- R4 readiness
- R4 verification strategy
- T-R4.51 browser verification
Code READMEs