Public game authentication
Beta: trusted backend mediation
The game signs players in with Firebase anonymous or Google authentication.
Every reference-backend request must verify the Firebase ID token (signature, issuer, audience, expiry and revocation policy).
Derive player identity only from verified UID. Tenant/project and permitted channel/item IDs are server configuration.
Never trust body/query player, tenant or project identifiers.
Keep DARTSTREAM_CLIENT_ID and DARTSTREAM_CLIENT_SECRET on the server and use the 0.3.3 machine client after publication.
Expose only load/save snapshot, read inventory, EMP consume and event publication. An EMP grant is authorized by a server-verified game action or one-time entitlement, not merely by the player’s request. Use stable, action-bound idempotency keys for both grant and consume; reject reuse with conflicting payloads. Enforce per-player and per-IP request limits, a small JSON body cap, event allowlists and an origin allowlist. A distributed deployment needs shared counters and idempotency storage; an in-memory counter is only a local-demo safeguard. Return sanitized 400/401/403/409/413/429/503 errors and never upstream credentials or internal diagnostics.
The reference sample must remove DS_CLIENT_SECRET entirely from Flutter source/build inputs.
Before hosting, scan built main.dart.js for secret_ and the actual removed secret without printing it; both must have zero matches.
If a secret was distributed or committed, revoke/rotate it through the owning credential workflow.
Issue #156 tracks the actual sample implementation and end-to-end tests; this document is a contract, not a delivered sample.
Proposed public-client grant (requires Brian’s review)
No production grant is enabled by this design.
An identity broker would verify Firebase identity and an application allowlist, then issue a five-minute audience-bound token
with fixed tenant, project, player UID, jti and a narrow read-mostly scope set.
Allowed operations: owned profile/inventory/session reads and constrained cloud-save access.
No billing, credential administration, project administration or inventory grants. The server retains economic mutations.
Renewal would require a fresh verified Firebase ID token; no long-lived DartStream refresh secret in browser storage.
Revoke a player/project grant via a server-side authorization epoch checked on every request; disabling a project must invalidate access.
Use TLS, bounded clock skew, exact audience/issuer validation, token redaction, action-bound idempotency and shared rate limits.
Bearer tokens remain replayable if stolen until expiry/revocation; jti alone does not prevent replay.
Consider proof-of-possession only if the additional key lifecycle is justified by demonstrated risk.
Threat model: bundle extraction exposes only public Firebase configuration; forged UIDs and project IDs are rejected; stolen tokens have narrow scope and short lifetime; grant farming stays behind server entitlement checks; XSS can steal in-browser bearer tokens, so avoid persistent browser token storage and enforce the application’s CSP; retries cannot double-grant or consume; cross-tenant requests cannot override token claims; generic upstream proxying is forbidden.
Compared with mediation, the grant can reduce a hop and server read bandwidth, but it expands the public authorization surface and requires per-operation ownership enforcement, shared revocation and abuse infrastructure. Keep mediation for beta. Implement a public grant only after design approval and negative isolation/replay/revocation tests.