Tech
Accounts and sign-in
One account for the website and the game — one-tap "Sign in with Google" on the web, the same Google account in the Windows, Android, iOS and Web clients (plus Sign in with Apple on iOS), server-side token verification, Zoen sessions, linking, recovery and the owner's setup steps.
Decision (owner, round 6): players sign in with one tap using their Google account, on the website and in the game.
One Zoen account per Google account; the same account works on every platform. Status: proposed design, built in
M6 (gateway) and M11 (site + store builds). Data: web-account.json → auth.
◆Flows per platform
| Where | How the player signs in | Technical flow |
|---|---|---|
Website (apps/site) | Google One Tap prompt on first visit + a "Sign in with Google" button in the header | Google Identity Services (GIS) for Web → ID token (JWT) → POST /v1/auth/google |
| Web build of the game | already signed in on the site; the game page reuses the session | site session cookie → short-lived game ticket → zone admission |
| Android app | one-tap bottom sheet ("Sign in with Google") | Android Credential Manager with the Google ID option → ID token → gateway |
| iOS app | "Sign in with Google" and "Sign in with Apple" buttons | Google Sign-In SDK / AuthenticationServices → ID token → gateway |
| Windows app | button opens the system browser (never an embedded web view), the player taps their Google account, the browser returns to the launcher | OAuth 2.0 authorization code + PKCE with a loopback redirect (RFC 8252) → gateway exchanges and verifies |
- iOS rule: Apple's App Review Guidelines require an equivalent privacy-focused login option when an app uses a third-party login such as Google; Sign in with Apple satisfies it. Re-check the current guideline wording at M11.
- An Apple-only player gets a normal Zoen account; they can link Google later (and the other way round).
◆Server side (gateway)
- Verify every Google ID token on the server: signature against Google's published keys (cached),
issis Google,audis one of our client IDs,expnot passed, and thenoncewe issued. Never trust a token the client only decoded. - Look up the account by the provider's stable subject id (
sub), not by email. Store the email only for account recovery notices (never shown publicly, never in the public API). - Issue Zoen's own session: a short-lived access token (15 min) and a rotating refresh token bound to the device; "Sign out everywhere" revokes every refresh token. Google tokens are not stored after verification.
- First sign-in creates the account and asks only for a display name (character names are separate).
- Rate-limit sign-in attempts per IP and per account; log every sign-in for the security system (Security & auto-ban).
◆Linking, recovery, deletion
- Settings → Account: link/unlink Google and Apple (at least one must stay linked).
- Lost Google access → support form on the site (not automated; identity checked by staff).
- Account deletion from the site and in-game (store requirement), with a 14-day grace period; ranking entries are anonymised, receipts kept only as long as the law requires.
◆Website one-tap details
- Use GIS One Tap (which uses the browser's FedCM support where available) plus the standard button. Show One Tap on the home page and on "Play in browser"; never on top of video or on checkout.
- Redirect mode must check the
g_csrf_tokencookie/body pair; popup mode uses the nonce. - Signed-in pages: Caravan Ledger, Redeem key, Account, the inventory playground's "load my character".
◆Owner setup (agents never create accounts)
- A Google Cloud project for Zoen (free) → OAuth consent screen (app name, logo, privacy policy and terms URLs).
- OAuth client IDs: Web (site origins), Android (package name + signing-certificate SHA-1), iOS (bundle id), Desktop (Windows launcher, loopback).
- Apple Developer account (OPEN-5) for Sign in with Apple and the iOS build.
- Give the client IDs to the agent as configuration (they are not secrets); any client secret goes into the server's secret store, never into the repo.
◆Tests
- Gateway: verification rejects wrong
aud, expired, bad signature, missing nonce; a replayed token fails. - Site: Playwright with a mocked GIS script (no real Google login in CI).
- Clients: PlayMode test with a stubbed provider returns a gateway session; the Windows flow is tested against a local fake authorization server.
Source: zoen/docs/tech/ACCOUNTS_AUTH.md · 768 words · edit the Markdown, not this page.
