Authentication
The browser client authenticates users through AWS Cognito via aws-amplify v5. Sign-in uses the Cognito hosted UI (OAuth authorization code flow with federated identity providers).
Configuration
Amplify is configured on mount in Skeleton.js:
- User pool ID and app client ID from config
- Cookie storage (7-day expiry, secure, domain from
COGNITO_COOKIE_DOMAIN) - OAuth domain, scopes (
openid,email,aws.cognito.signin.user.admin),responseType: "code"
Redirect URLs come from COGNITO_REDIRECT_LOGIN and COGNITO_REDIRECT_LOGOUT. See Configuration.
Sign-in flow
- User clicks login →
Auth.federatedSignIn()(inLogInOutButton.js). - Browser redirects to Cognito hosted UI.
- On success, Cognito redirects back with an authorization code; Amplify exchanges it for tokens.
- On success, Cognito redirects back with an authorization code; Amplify exchanges it for tokens.
resolveAuthSession()stores the user and JWT in ZustandauthSession; UI components read it viauseAuthSession().
Session bootstrap
Skeleton calls resolveAuthSession() on load:
- Success → marks
localStorage.wasLoggedIn = "1". - Failure with prior
wasLoggedIn, no intentional logout, and a non-anonymous route → session expired; auto-triggersfederatedSignIn().
Token refresh
getAuthTokenFromSession() returns a cached JWT while it is still valid (with a 5-minute buffer before expiry). When the token is stale or missing, it silently calls Auth.currentAuthenticatedUser() again so Amplify can refresh the ID token without flashing the login UI.
callAuthApi retries once with a forced session refresh on HTTP 401/403 before redirecting to Cognito.
Sign-out
UserSettingsModal.js sets sessionStorage.intentionalLogout = "1" before Auth.signOut() so the expiry handler does not immediately re-login.
User profile (globalMe)
After login, useProfileBootstrap calls fetchProfile() (me_profile), which populates Zustand globalMe (bots, settings, activeGames, etc.). Me.js calls fetchDashboard() (me_dashboard) on the /me page for games, challenges, and notifications.
New user onboarding
If the backend returns an incomplete profile, NewProfile.js prompts the user to set a display name and preferences.
Token usage
- Auth API calls —
Authorization: Bearer <jwt>viacallAuthApi - WebSocket — token sent on subscribe (see WebSockets)
- Push notifications — token sent with
save_push(see Notifications)
Profile updates
Email and password changes go through Amplify APIs in UserSettingsModal, not the node-backend authQuery layer.
Cognito setup (ops)
Pool configuration, callback URLs, and identity providers are documented in Backend deployment. Dev and prod use separate pools; tokens are not interchangeable across stages.