N.E.S.T. Chat Authentication

How nest.thephenom.app authenticates to chat.thephenom.app: which Cognito pool mints tokens, which SPA client ID is used, how Synapse validates the JWT, and the in-app recovery surfaces for broken chat sessions.

Current configuration

nest.thephenom.app uses the phenom-prod Cognito user pool to authenticate users. The same pool issues tokens that the prod Synapse cluster (chat.thephenom.app) validates, giving a single sign-on experience: sign in to N.E.S.T. and chat works without a second credential exchange.

Setting Value
Cognito pool phenom-prod
Pool ID us-east-1_knEL7cqS3
SPA client phenom-prod-nest-spa
SPA client ID 5vlgjrab90897c45ls9jkf9s2p
Auth flows on client SRP, PASSWORD, REFRESH (public client, no secret)
Chat homeserver chat.thephenom.app (prod Synapse)
Hasura URL (prod Worker) api.thephenom.app/v1/graphql

The VITE_COGNITO_USER_POOL_ID and VITE_COGNITO_CLIENT_ID build vars are hardcoded in the layer-3-deploy-pages-prod job in .github/workflows/nest-ci.yml. The COGNITO_USER_POOL_ID var in nest-api/wrangler.toml [env.production].vars matches the same pool. All three (SPA, Worker, Synapse) validate tokens against the same Cognito JWKS endpoint.

How Synapse validates Cognito JWTs

Synapse’s jwt_config block (managed in phenom-infra/environments/production/) is wired to the prod pool. All three Synapse instances (dev, staging, prod) have their own jwt_config pointing at their respective pool’s JWKS; the prod instance validates against us-east-1_knEL7cqS3.

The jwt_audiences list on the prod Synapse includes 5vlgjrab90897c45ls9jkf9s2p (the phenom-prod-nest-spa app client ID), so tokens minted by the SPA are accepted.

User-facing chat recovery surfaces

Three surfaces in the N.E.S.T. UI expose chat session recovery:

1. Top-right avatar dropdown (ProfileDropdown)

Available on every feature page. Two relevant items:

  • Log out – soft Cognito sign-out only.
  • Sign out and reset chat – calls resetChatStorage() first, which removes the persisted Matrix client state (IndexedDB databases prefixed matrix-js-sdk or crypto.matrix.org, mx_* / matrix_* keys in local and session storage, any service-worker cache containing matrix or chat), then chains cognitoSignOut() and broadcastAuthReset.

2. Bottom-left sidebar avatar dropdown (NavUser)

Same two items as the top-right dropdown, mirrored into app-sidebar.tsx. Both dropdowns should stay in sync; if one gets a new menu item the other needs it too.

3. Settings (default /settings landing)

The ChatConnectionCard renders at /settings (the profile landing). It shows:

  • Current MXID
  • Homeserver URL
  • Synapse admin status (badge)

Two action buttons:

  • Reconnect to chat – calls reconnectChatClient(cognitoToken), which composes resetChatStorage() with getMatrixSession() for a chat-only session rebuild without signing out of N.E.S.T.
  • Sign out everywhere – same full teardown as the dropdown’s “Sign out and reset chat”.

The card is the low-friction, discoverable path. The dropdown items are the escape hatch for users on a wedged page that has not finished rendering.

Known open items

Item Status
Avatar migration Staff avatars point at mxc URLs on the old staging Synapse MXID. The prod Synapse cannot resolve them without federation (not configured). Each person’s avatar must be re-uploaded against their prod-pool MXID in Hasura users.avatar_url. Not yet ticketed.
Synapse admin re-grant Migrating pools means a different Cognito sub claim, which means a different MXID. Synapse admin status must be re-granted to every staff person’s new prod-pool MXID via the Synapse Admin API. Not yet ticketed.
BroadcastChannel loop (latent) logout() and logoutAndReset() both broadcast AUTH_RESET. The handler in main.tsx calls useAuthStore.getState().logout() on receipt, which rebroadcasts. Two or more open N.E.S.T. tabs at logout time produce an infinite ping-pong (sign-in page reloads continuously). Close all tabs to recover. The handler needs to use a silent state-reset instead of the action that broadcasts.
dev-nest.thephenom.app pool alignment The dev surface may still point at a different Cognito pool or homeserver. Verify and apply the same cutover if needed.