Skip to content

[T3 Connect] TypeScript SDK: let short-lived auth tokens survive reconnects - #6011

Draft
bradleyshep wants to merge 1 commit into
masterfrom
bradley/ts-sdk-token-provider
Draft

bradleyshep wants to merge 1 commit into
masterfrom
bradley/ts-sdk-token-provider

Conversation

@bradleyshep

@bradleyshep bradleyshep commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Part of the work to move T3 Code's T3 Connect relay onto SpacetimeDB.

Description of Changes

withToken only took a string, and ConnectionManager re-applies the session's token on every automatic rebuild. For third-party OIDC tokens such as Clerk session JWTs (about a minute of lifetime), that token is the original JWT. Once it expired, every reconnect failed with 401 and retried forever. React apps also had no way to switch identity while mounted, because retain() ignores a new builder once a connection is live.

  • withToken now also accepts a TokenProvider: a sync or async function called before every connection attempt, including automatic reconnects.
  • A builder with a token provider never has its token overwritten by the session's last token.
  • useSpacetimeDB() gains reconnect(builder), which tears down the current connection and rebuilds from a fresh builder, for example after sign-in or sign-out.
  • The Clerk auth guide shows the provider form.

Where this matters: a client that opens a fresh connection for each short task can fetch a token first and pass a string, so it doesn't need this. It matters for long-lived connections that the SDK reconnects on its own, such as the React provider behind a live dashboard, where the token has usually expired by the time the SDK reconnects. A callback affects the next connection attempt; switching identity on an open connection still needs reconnect(builder).

Split out of #6005 / #6006.

API and ABI breaking changes

None. withToken accepts a function in addition to a string, and reconnect is new.

Rollback safety impact

n/a

Expected complexity level and risk

  1. It touches ConnectionManager's rebuild path; the string-token path is unchanged.

Worth a reviewer's eye:

  • A provider that returns undefined connects anonymously on every attempt, so a signed-out app gets a new anonymous identity on each reconnect. With a string token or none, the manager still resumes the session's token as before.
  • reconnect is a required member of the React ConnectionState type, matching Svelte's. Code that builds a ConnectionState by hand, such as a test mock, needs to add it.

Testing

  • pnpm test in crates/bindings-typescript (327 passing), including new reconnect and token-provider tests
  • A React client and a React Native client with Clerk tokens stay connected across reconnects past the token's expiry
  • Reviewer: sanity-check the ConnectionManager change against other auth providers

@bradleyshep
bradleyshep force-pushed the bradley/ts-sdk-token-provider branch from 3470ea4 to bc7709b Compare September 30, 2026 17:38
@bradleyshep bradleyshep changed the title TypeScript SDK: let short-lived auth tokens survive reconnects [T3 Connect] TypeScript SDK: let short-lived auth tokens survive reconnects Sep 30, 2026
`withToken` only took a string, and the ConnectionManager re-applies the
session's token on every automatic rebuild. For third-party OIDC tokens
such as Clerk session JWTs (about a minute of lifetime) that token is
the original JWT, so once it expired every reconnect failed with 401 and
retried forever. React apps also had no way to switch identity while
mounted: `retain()` ignores a new builder once a connection is live.

`withToken` now also accepts a `TokenProvider`, a sync or async function
that is called on every connection attempt: the initial build, automatic
reconnects, resume and zombie revival, and `rebuild()`. Its value is that
attempt's token (`undefined` connects anonymously) and `conn.token`
reflects it. A throw or rejection reaches `onConnectError`, so the
manager retries it with backoff. The manager no longer resumes the
session token over a builder with a provider; string tokens resume as
before. `TokenProvider` is exported from the package root.

The React context gains `reconnect(builder)`, calling
`ConnectionManager.rebuild()` like the Svelte provider does. The Clerk
guide now passes a provider instead of a token fetched once.
@bradleyshep
bradleyshep force-pushed the bradley/ts-sdk-token-provider branch from bc7709b to 8ce8ec2 Compare October 1, 2026 17:26

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant