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..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,7 +752,21 @@ 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 == "") + { + // 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 AuthToken.SaveToken(token); +#endif LocalIdentity = identity; OnConnected?.Invoke(); @@ -796,6 +810,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..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,7 +1364,21 @@ 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 == "") + { + // 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 AuthToken.SaveToken(token); +#endif LocalIdentity = identity; conn.Db.Circle.OnInsert += CircleOnInsert; @@ -1383,6 +1397,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