projects / easemysemester / decisions
Google OAuth only for the mobile PWA
v2 shipped hand-rolled Google OAuth with an invite list, email plus role deciding access, a revoked account's sign-in refused before a session is minted, and citations verified across eight books; auth was later replaced by email and password.
decision · superseded · updated 2026-09-17 · EaseMySemester case study
See overview and mobile PWA design.
Context
The mobile PWA design needed a sign-in screen and had to settle how an account gets created.
Decision
Google OAuth only. One button does both sign in and sign up; the account is created on first success. No email and password. A line on the sign-in screen states this directly, to remove any confusion about a missing signup link.
Why
Settled with the architect and PM as one of the design's locked decisions, alongside dropping the paywall, exam countdowns, streaks and offline downloads from the earlier six-screen pass.
Consequences
The scope statement on the sign-in screen commits to requesting only name and email from Google, not broader profile access. A wrong Google account is handled with a "not you?" affordance on the following screen rather than a separate account-switch flow.
Built, then the invite list was dropped
The first build (2026-09-08) was hand-rolled authorization-code OAuth with no auth library and
no local ID-token verification, Google establishing identity and an invite list (email plus
role) deciding access. A revoked account's next sign-in returned the inactive row and was
refused before a session, fixed after review found the callback could mint a session for a
revoked account regardless of active.
The next day (2026-09-09), the invite list was dropped: establishUser finds or creates an
account for a verified Google sub, so the same callback serves both a first-time sign-up and a
returning sign-in, and a student who signs out for a year returns to their own history rather
than a second empty account. The invites table stays in the schema and stops being read,
rather than being dropped in the same change, since this is a production database with no
staging to roll back to. A new account is written as role STUDENT literally in the insert;
ADMIN is now granted only by someone with direct database access. active becomes the sole
access gate, so revocation had to be re-verified end to end: a revoked student could otherwise
re-create their own access by signing in again.
A single guard module reads role and active from the database on every request rather than
trusting the session cookie, so revoking a student takes effect on their next request. A revoked
account that completes the OAuth round trip is refused before a session is minted; the first
build minted one regardless, caught in review and fixed same day. The invite-gated build also
carried a route-protection test that enumerates every guarded route from one list, and a
citation spot-check across eight books, offsets 11 to 363, all correct, which was the check
meant to separate this build from v1's citations that were off by up to 42 pages.
Status
Shipped 2026-09-08 (invite-gated) and 2026-09-09 (invite list dropped, closing issue #38). Superseded: the design bundle synced 2026-09-16 states Google was dropped in favour of email and password sign-in with a demo link on the landing page, because the consent screen was doing nothing for the students. See the replacement decision.