diff --git a/docs/prd/06-technical-platform.md b/docs/prd/06-technical-platform.md index 93d5f232..75b27db6 100644 --- a/docs/prd/06-technical-platform.md +++ b/docs/prd/06-technical-platform.md @@ -133,14 +133,19 @@ For safety, the backend should use GCS **preconditions** (`ifGenerationMatch`) w ### Authentication — Google Identity Platform -Players authenticate via Google Sign-In. This aligns with PRD 04's decision that player identity is an email address (via Google Auth). +OpenStars authentication rollout is staged to de-risk delivery: -- Frontend uses the Google Identity Services SDK for sign-in -- Backend validates Google ID tokens on each API request -- The `username` field in game state maps to the authenticated email +1. **UI sign-in gate first** (current): frontend uses Google Identity Services (GIS) and requires login before lobby access. +2. **Backend bearer-token validation later**: backend validates Google ID tokens and extracts identity server-side. + +Identity model decisions remain the same: + +- `username` in game state maps to authenticated email identity - No custom auth system, no password storage -For local development, auth can be bypassed or mocked (see Local Development below). +During stage 1, the frontend maps the signed-in email to `X-Player` when calling the existing API (see PRD 50). This keeps endpoint contracts stable while backend authorisation work is pending. + +For local development, auth can be bypassed or mocked when needed (see Local Development below). ## Docker Strategy diff --git a/docs/prd/50-api.md b/docs/prd/50-api.md index 7f2e19f5..6b96ad84 100644 --- a/docs/prd/50-api.md +++ b/docs/prd/50-api.md @@ -16,22 +16,29 @@ All endpoints are shown as full paths (e.g. `/api/v1/games`). The `/api/v1` pref ## Authentication -Phase 1 has **no authentication**. The player identity is passed via a request header on all player-scoped endpoints: +Current backend API auth is a transitional model: + +- The backend still uses `X-Player` for player identity on player-scoped endpoints +- The frontend sign-in UX may require Google login before showing the games list (see PRD 60) +- During this transition, the frontend maps the signed-in Google email to `X-Player` +- The backend trusts `X-Player` and does not validate Google bearer tokens yet + +The player identity is passed via a request header on player-scoped endpoints: ``` X-Player: {username} ``` -The backend trusts this value — there is no token validation or identity verification. This keeps the initial implementation simple and removes any dependency on Google Identity or auth infrastructure. +The backend trusts this value — there is no token validation or identity verification in this phase. **Examples:** - `GET /api/v1/games/my-game/state` with `X-Player: tim` — Tim's view of the game - `POST /api/v1/games/my-game/commands` with `X-Player: matt` — submit commands as Matt - `GET /api/v1/games/my-game/commands` with `X-Player: tim` — retrieve Tim's submitted commands -The `X-Player` header is required on all player-scoped and participant-gated endpoints: `GET /games/{game_id}`, `GET /state`, `GET /galaxy`, `GET /commands`, `POST /commands`, and `POST /resolve`. It is optional on `GET /games` (filters to games containing that player; omit to list all games). +The `X-Player` header is required on all player-scoped and participant-gated endpoints: `GET /games/{game_id}`, `GET /state`, `GET /galaxy`, `GET /commands`, `POST /commands`, and `POST /resolve`. It is optional on `GET /games` (filters to games containing that player; omit to list all games in non-production/dev scenarios). -Authentication (Google Identity) will be added in Phase 5 (Multiplayer), replacing `X-Player` with an `Authorization: Bearer ` header and server-side identity extraction. The switch is a single middleware change — no endpoint signatures need updating. +Backend authentication (Google bearer token validation) will be added in a follow-up phase, replacing `X-Player` with `Authorization: Bearer ` and server-side identity extraction. Endpoint paths and payloads do not need to change for that migration. --- diff --git a/docs/prd/60-ui-overview.md b/docs/prd/60-ui-overview.md index 23ab3316..58d3aba5 100644 --- a/docs/prd/60-ui-overview.md +++ b/docs/prd/60-ui-overview.md @@ -32,6 +32,33 @@ Reference: `docs/references/stars-1995-screenshot-51464.jpg` - **UI panels:** React + TypeScript + Tailwind CSS + shadcn/ui components - **State management:** React context or Zustand — TBD during implementation, keep it simple - **Layout:** CSS Grid for the overall structure, absolute positioning for map overlays +- **Identity UI:** Google Identity Services (GIS) for frontend sign-in + +## Access and Sign-in Gate + +The frontend must require Google sign-in **before** showing the game lobby/games list. + +- Initial route shows a dedicated sign-in screen with OpenStars! branding and a single primary action: **Sign in with Google** +- Unauthenticated users cannot view the games list, create a game, or open any game route +- On successful sign-in, the user is redirected to the lobby (games list) +- Sign out returns the user to the sign-in screen and clears in-memory lobby/game UI state + +### Transitional architecture (UI now, backend authorisation later) + +The sign-in gate is introduced in the UI before backend token validation is implemented. + +- Frontend obtains Google identity (email + display name) from GIS +- Frontend continues to call existing API endpoints that currently use `X-Player` +- `X-Player` is populated from the signed-in Google email during this transition period +- Backend remains unchanged in this phase (no bearer-token validation yet) + +This keeps the UX and route-guard behaviour aligned with the eventual multiplayer auth model while avoiding a coupled frontend/backend migration. + +### Error and loading states + +- While GIS initialises, show a loading state on the sign-in screen +- If GIS fails to load or sign-in fails, show a clear retryable error message +- If stored sign-in state is invalid/expired, return to sign-in screen and require login again ## Screen Layout @@ -140,11 +167,11 @@ Phase 2 (Basic UI) implements the minimum needed to interact with the Phase 1 en - Research allocation - Race/trait configuration - Battle replay viewer -- Game lobby / game creation UI (Phase 5 — multiplayer) - Chat / messaging between players - Notifications (email/push for "it's your turn") - Planet habitability visualisation - Minimap +- Backend bearer-token validation and authorisation enforcement (follow-up phase) ## Screen Size diff --git a/tasks/2026-04-20-google-auth-ui-gate.md b/tasks/2026-04-20-google-auth-ui-gate.md new file mode 100644 index 00000000..0805866d --- /dev/null +++ b/tasks/2026-04-20-google-auth-ui-gate.md @@ -0,0 +1,71 @@ +# Google Auth UI Gate for Lobby Access + +**PRDs:** +- [60-ui-overview.md](../docs/prd/60-ui-overview.md) — Access and Sign-in Gate +- [50-api.md](../docs/prd/50-api.md) — transitional `X-Player` auth model +- [06-technical-platform.md](../docs/prd/06-technical-platform.md) — staged Google Identity rollout + +Implement Google sign-in in the frontend so users must authenticate before they can access the games list (lobby) or enter a game route. Backend bearer-token validation is explicitly out of scope for this task. + +--- + +## Step 1 — Frontend auth foundations and configuration + +- [ ] Add frontend auth configuration for Google Identity Services (client ID, environment wiring, and startup validation) +- [ ] Add an auth domain model (`unauthenticated` / `loading` / `authenticated` / `error`) and shared types for signed-in user identity +- [ ] Add a small auth service layer that wraps GIS initialisation and sign-in/sign-out operations +- [ ] Persist minimal sign-in session state appropriate for SPA reloads (without storing sensitive tokens long-term) +- [ ] Unit tests: + - Auth service initialises GIS successfully + - Auth service returns a retryable error when GIS fails to load + - Auth state transitions are deterministic for success/failure/sign-out paths + +## Step 2 — Route guarding and login screen UX + +- [ ] Add a dedicated login screen as the default unauthenticated entry point +- [ ] Gate lobby (games list), game creation, and game routes behind authentication +- [ ] Redirect authenticated users from login screen to lobby +- [ ] Redirect unauthenticated users trying to access protected routes back to login +- [ ] Add loading and error UI states on the login screen for GIS initialisation/sign-in failures +- [ ] Component/router tests: + - Unauthenticated user sees login screen and cannot access lobby content + - Authenticated user is redirected to lobby + - Protected route navigation bounces unauthenticated users to login + - Login error state renders retry affordance + +## Step 3 — API client integration with transitional identity header + +- [ ] Update frontend API client wiring so authenticated identity drives `X-Player` +- [ ] Use signed-in Google email as the `X-Player` value for existing endpoints +- [ ] Ensure API calls are blocked or short-circuited while auth is unresolved/unauthenticated +- [ ] Preserve existing backend contract (no bearer-token changes in this task) +- [ ] Unit tests: + - API client sends `X-Player` header from authenticated email + - API client omits protected requests when user is signed out + - Existing game list/game state calls continue to decode successfully under authenticated flow + +## Step 4 — Header/session controls and sign-out behaviour + +- [ ] Add signed-in identity display in lobby/top-level UI (email or display name) +- [ ] Add sign-out action accessible from lobby/game shell +- [ ] On sign-out, clear frontend auth/session state and return to login screen +- [ ] Ensure stale game/lobby data is not shown after sign-out +- [ ] Component/state tests: + - Sign-out clears auth state and triggers login redirect + - Post sign-out render does not expose previously loaded game list data + +## Step 5 — Integration coverage and documentation touch-ups + +- [ ] Add/update frontend integration tests for the full login → lobby → sign-out flow +- [ ] Update frontend developer documentation for required Google client ID configuration and local-dev auth behaviour +- [ ] Confirm lint/typecheck/tests pass for frontend workspace +- [ ] Verification commands (from `frontend/`): + - `npm run lint` + - `npm run typecheck` + - `npm test` + +## Notes + +- Backend authorisation/token validation is intentionally deferred; follow-up work will migrate from `X-Player` to bearer tokens. +- Keep implementation compatible with existing local development workflow. +- Use British English in UI copy and docs where practical.