Skip to main content

Authentication

Use the server engine auth() hook to authenticate a player before RPGJS lets the WebSocket connection join a room. In MMORPG mode, RPGJS connects to one room at a time. The first connection usually targets lobby-*, then map changes reconnect the player to map-* rooms. The auth() hook is called for each RPGJS room connection. If it throws, the connection is refused before a RpgPlayer is created or restored in that room.

Mental model

Use auth() as the global RPGJS gate:
  • it runs on the lobby connection;
  • it runs again when the player reconnects to a map room;
  • it accepts or refuses the room connection;
  • it returns the stable public player id used by RPGJS and Signe user collections.
Use Signe guards for narrower authorization after authentication, such as protecting an admin action, a custom room, or an HTTP endpoint.

Server

Add auth() to the server engine hooks. Return the stable public player id for the authenticated account.
The returned id becomes the Signe/RPGJS publicId used by @users(RpgPlayer). Return the same id for the same account on every room connection so the player keeps the same identity when moving between maps. If auth() returns undefined, RPGJS keeps the default behavior and lets the room system generate the public player id.

Use the authenticated id for save slots

Authentication and save loading are separate operations:
  1. auth() verifies the credential and returns the account’s stable public id.
  2. RPGJS exposes that id as player.id to server-side game code and storage strategies.
  3. A SaveStorageStrategy uses player.id to list, save, or retrieve that account’s slots.
  4. The game explicitly calls player.load(slot) after it has selected a slot.
Returning the same id does not automatically call player.load(). It only gives the server a stable, trusted key with which to find the correct saves.
Do not use the private WebSocket sessionId as the long-term account key. It is useful for reconnecting a browser, but it can change when the player clears local storage, changes device, or starts a new browser session. Similarly, do not accept a playerId sent in a save/load request from the browser. Use the authenticated player.id already attached to the server-side RpgPlayer instance.

What happens on reconnect

  • A map change authenticates the connection again and transfers the live player state to the destination room. Do not reload a save slot on every map join.
  • A browser refresh may restore the current private session and room state, but this is not a long-term save load.
  • A new session can authenticate as the same account. Your login or title-screen flow must then list or load the desired slot explicitly.
For a one-character game, loading slot 0 in the server-side onConnected hook is a simple policy. For multiple characters, list the slots after authentication and let the player select one. See When an MMORPG save is loaded for both approaches.

Public lobby, protected maps

If your lobby must stay public, return undefined for lobby rooms and only enforce authentication on map rooms:
With this pattern, any client can enter the lobby, but a map connection is refused unless auth() returns a valid stable player id. If the public lobby displays account save slots, authenticate the account before listing them. A generated anonymous lobby id cannot identify the account’s long-term saves.

Client

In a browser, send credentials through the connection query. RPGJS sends this query on the initial connection and again when the player reconnects to another room.
On map changes, RPGJS keeps its own session and transfer parameters and merges your query into the reconnect request:
Handle refused authentication with the client engine onConnectError hook:
When the server refuses the connection, the MMORPG client waits for the server acceptance packet before starting the visual scene. This means an invalid token does not enter a half-loaded map; onConnectError is the place to recover. The client onConnected hook runs only after the server accepts the RPGJS connection. By default, the MMORPG client does not retry a connection that closes before RPGJS accepts it. This avoids retry loops when a token is invalid. If you need custom retry behavior, pass PartySocket options through socketOptions:

Guards

auth() is global RPGJS authentication. It decides whether the player may enter the game and which public id represents the player. Signe room guards are still useful for more specific authorization rules:
  • protect a custom room;
  • protect one action;
  • protect an HTTP request handler;
  • check roles or permissions after authentication.
For example, use auth() to identify the player, then use a Signe @Guard() to restrict an admin action.