From 58bb889874c9de26f0c482452219ef33dc51f2c9 Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Thu, 21 May 2026 14:10:23 -0400 Subject: [PATCH 1/3] Document server-issued token reconnect behavior --- .../00300-unity-tutorial/00300-part-2.md | 9 ++++++++ .../00300-unity-tutorial/00400-part-3.md | 9 ++++++++ .../00500-authentication.md | 22 +++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md index 3df6b0b735a..c56d43e1b18 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md @@ -752,7 +752,14 @@ public class GameManager : MonoBehaviour void HandleConnect(DbConnection _conn, Identity identity, string token) { Debug.Log("Connected."); +#if UNITY_WEBGL && !UNITY_EDITOR + if (AuthToken.Token == "") + { + AuthToken.SaveToken(token); + } +#else AuthToken.SaveToken(token); +#endif LocalIdentity = identity; OnConnected?.Invoke(); @@ -796,6 +803,8 @@ public class GameManager : MonoBehaviour } ``` +> Unity WebGL needs one extra precaution here. Browser WebSocket APIs cannot set an `Authorization` header, so reconnecting with a saved server-issued token may yield a short-lived WebSocket token in `HandleConnect`. The `#if UNITY_WEBGL` guard keeps the original saved token instead of overwriting it during reconnect. + Here we configure the connection to the database, by passing it some callbacks in addition to providing the `SERVER_URI` and `MODULE_NAME` to the connection. When the client connects, the SpacetimeDB SDK will call the `HandleConnect` method, allowing us to start up the game. In our `HandleConnect` callback we build a subscription and call `Subscribe`, subscribing to all data in the database. This causes SpacetimeDB to synchronize the state of all your tables with your Unity client's SDK client cache. diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md index 8de2e8d1610..03f3c60fa14 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md @@ -1364,7 +1364,14 @@ Next lets add some callbacks when rows change in the database. Modify the `Handl void HandleConnect(DbConnection conn, Identity identity, string token) { Debug.Log("Connected."); +#if UNITY_WEBGL && !UNITY_EDITOR + if (AuthToken.Token == "") + { + AuthToken.SaveToken(token); + } +#else AuthToken.SaveToken(token); +#endif LocalIdentity = identity; conn.Db.Circle.OnInsert += CircleOnInsert; @@ -1383,6 +1390,8 @@ Next lets add some callbacks when rows change in the database. Modify the `Handl } ``` +Keep the same WebGL guard from Part 2 here as well. On Unity WebGL, a reconnect can surface a short-lived WebSocket token in `HandleConnect`, so you should not overwrite an already-saved long-lived server-issued token. + Next add the following implementations for those callbacks to the `GameManager` class. ```cs diff --git a/docs/docs/00200-core-concepts/00500-authentication.md b/docs/docs/00200-core-concepts/00500-authentication.md index 54fc79a95a0..c118245c946 100644 --- a/docs/docs/00200-core-concepts/00500-authentication.md +++ b/docs/docs/00200-core-concepts/00500-authentication.md @@ -11,6 +11,28 @@ needs, or even implement your own. If you're new to OIDC, check out our [blog post about OIDC](https://spacetimedb.com/blog/who-are-you) to learn more about how OIDC works and why it's a great choice for authentication. +## Server-issued tokens and reconnects + +If a client connects without supplying a token, SpacetimeDB creates a new +identity and returns a server-issued token for that identity. If you want later +connections to keep using that same identity, persist that returned token and +pass it back into the SDK on reconnect. + +On platforms that can send an `Authorization` header during the WebSocket +handshake, the SDK can reuse that saved token directly. On platforms that cannot +set custom WebSocket headers, the SDK first exchanges the saved token for a +short-lived WebSocket token through +[`POST /v1/identity/websocket-token`](/docs/http/identity#post-v1identitywebsocket-token), +then sends only that short-lived token in the WebSocket URL. + +This matters when you persist tokens on the client: + +- Save the long-lived server-issued token that establishes the user's identity. +- Do not overwrite an already-saved long-lived token with a short-lived + WebSocket token received during reconnect. +- Expect this distinction on browser-style transports where WebSocket headers + are unavailable, such as Unity WebGL builds. + ## SpacetimeAuth To make it easier to get started with authentication, SpacetimeDB offers From 84086e7726f3bebaf0696648bbfbd3bc05b386d0 Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Thu, 21 May 2026 17:53:55 -0400 Subject: [PATCH 2/3] Clarify Unity WebGL token guard --- .../00300-tutorials/00300-unity-tutorial/00300-part-2.md | 4 ++++ .../00300-tutorials/00300-unity-tutorial/00400-part-3.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md index c56d43e1b18..25f907e1525 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md @@ -755,6 +755,10 @@ public class GameManager : MonoBehaviour #if UNITY_WEBGL && !UNITY_EDITOR if (AuthToken.Token == "") { + // No token was supplied to the connection, so this is the + // long-lived server-issued token for the new identity. Save it. + // If a token already exists, this connect may have used a + // short-lived WebSocket token, which should not overwrite it. AuthToken.SaveToken(token); } #else diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md index 03f3c60fa14..5e45f758bf4 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md @@ -1367,6 +1367,10 @@ Next lets add some callbacks when rows change in the database. Modify the `Handl #if UNITY_WEBGL && !UNITY_EDITOR if (AuthToken.Token == "") { + // No token was supplied to the connection, so this is the + // long-lived server-issued token for the new identity. Save it. + // If a token already exists, this connect may have used a + // short-lived WebSocket token, which should not overwrite it. AuthToken.SaveToken(token); } #else From 37b17041f03c660f4b957b1426202e340f308d19 Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Thu, 21 May 2026 17:56:11 -0400 Subject: [PATCH 3/3] Explain Unity WebGL preprocessor guard --- .../00300-tutorials/00300-unity-tutorial/00300-part-2.md | 3 +++ .../00300-tutorials/00300-unity-tutorial/00400-part-3.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md index 25f907e1525..b6d0f9166eb 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00300-part-2.md @@ -752,6 +752,9 @@ public class GameManager : MonoBehaviour void HandleConnect(DbConnection _conn, Identity identity, string token) { Debug.Log("Connected."); + // Only the WebGL player has the browser WebSocket header limitation. + // The Unity Editor uses the normal desktop transport even when the + // selected build target is WebGL, so keep the normal behavior there. #if UNITY_WEBGL && !UNITY_EDITOR if (AuthToken.Token == "") { diff --git a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md index 5e45f758bf4..214db1647f8 100644 --- a/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md +++ b/docs/docs/00100-intro/00300-tutorials/00300-unity-tutorial/00400-part-3.md @@ -1364,6 +1364,9 @@ Next lets add some callbacks when rows change in the database. Modify the `Handl void HandleConnect(DbConnection conn, Identity identity, string token) { Debug.Log("Connected."); + // Only the WebGL player has the browser WebSocket header limitation. + // The Unity Editor uses the normal desktop transport even when the + // selected build target is WebGL, so keep the normal behavior there. #if UNITY_WEBGL && !UNITY_EDITOR if (AuthToken.Token == "") {