Login handshake - rebaserHEAD/NexusForever GitHub Wiki

explanation, committed verified 2026-10-14 stable a4e75b18

How the client gets from a password to a character in the world: three servers, two tokens handed from one to the next, and where each step lives. Read from the code, and seen working on a local server.

The shape

Three hops, two tokens

The client talks to three servers in turn, and each hop hands it what the next one asks for.

sequenceDiagram
    participant C as Client
    participant S as STS
    participant A as Auth
    participant W as World
    C->>S: email, password proof
    S-->>C: game token
    C->>A: game token
    A-->>C: session key, realm address
    C->>W: session key
    W-->>C: realm and character lists
Loading
  1. STS proves the password and issues a game token.
  2. Auth takes the game token, picks a realm, and issues a session key along with that realm's address.
  3. World takes the session key, and from then on the client is in the game: realm list, character list, character select, and into a map.

Vocabulary

Term Meaning
SRP6 The password check. The client proves it knows the password without sending it; the server stores only a salt and a verifier
Game token A GUID the STS server writes to the account's gameToken column. The auth server looks the account up by it
Session key 16 random bytes the auth server writes to the account's sessionKey column. The world server looks the account up by it, and it also keys the world connection's encryption
Realm A world server the client can pick. Each one is a row of the auth database's server table

The two columns are also described on upstream's database documentation.

Each hop

STS: the password

The STS server speaks a text protocol, STS/1.0: a request line naming a path, a couple of headers, and an XML body.

  1. The client connects and starts the login with its email. The server looks the account up, sets up SRP6 from the stored salt and verifier, and sends back its half of the exchange.
  2. The client answers with its own half and its proof. The server checks the proof, sends its own, and from there both sides encrypt the connection.
  3. The client asks for a game token. The server writes a new GUID to the account and sends it.

Auth: the realm

The auth server speaks the game's binary protocol, the same framing as the world server.

  1. It greets the client, and the client answers with its build number, email and game token.
  2. The server refuses any build but 16042, looks the account up by email and game token, and checks for bans and suspensions.
  3. It picks the first realm that's online, generates a session key, writes it to the account, and sends it with the realm's name, address and port.

World: into the game

  1. The world server greets the client, and the client answers with its session key.
  2. The server looks the account up by the session key, loads it, and switches the connection's encryption to a key derived from the session key.
  3. The client asks for the realm list and the character list. The character list comes straight from the character database, with the account's currencies, unlocks and entitlements alongside.
  4. From character select the client enters a map, and the game begins.

Switching realm from the realm list repeats the last hop: the world server issues a new session key and tells the client where to go.

The knobs

Knob Where Effect
The realm's address host and port of the realm's row in the auth database's server table Where the auth server sends the client. The seeded row is 127.0.0.1 and 24000, which only works for a client on the same machine
Realm:RealmId WorldServer.json, or the Aspire host Which server row this world server is. It must exist, or the world server won't start
The account's role account create <email> <password> <role> Doesn't affect logging in, but without one the account can't use commands

Where the code lives

Piece Path
STS login and game token Source/NexusForever.StsServer/Network/Message/Handler/AuthenticationHandler.cs
SRP6 Source/NexusForever.Cryptography/Srp6Provider.cs, with the verifier made by PasswordProvider.cs beside it
Auth hello, realm pick and session key Source/NexusForever.AuthServer/Network/Message/Handler/HelloAuthHandler.cs
The realm list behind it Source/NexusForever.Game/Server/ServerManager.cs
World hello and session key Source/NexusForever.WorldServer/Network/Message/Handler/Authentication/ClientHelloRealmHandler.cs
Packet encryption Source/NexusForever.Cryptography/PacketCrypt.cs
Realm switching Source/NexusForever.WorldServer/Network/Message/Handler/Character/ClientSelectRealmHandler.cs
⚠️ **GitHub.com Fallback** ⚠️