Login can be thought of as three separate steps for the client:
- Entering a username/password and getting to the realm list.
- Selecting a realm and getting to the character screen.
- Selecting a character and getting into the world.
Each step builds upon the previous and it is possible to go backwards in the process.
The client only expects connections to two different servers:
- The Login Server (default port 3724) which handles initial login using Login Packets.
- The World Server (default port 8085) which handles the character screen and gameplay on the realm using World Packets.
Authentication with the login server happens through a variant of the SRP6 protocol using Login Packets. This allows the client and server to prove to each other that they both know the same password without revealing what the password is to eavesdroppers. The client and server can use this shared secret to create a session key which is used for encrypting the headers of World Packets when connecting to the World Server.
Login message exchange:
- Client asks for a login challenge by sending its build number and account name
- Server sends SRP authentication data
- Client sends SRP proof
- Server accepts this proof and send its own, or reject and close the connection
When the client is accepted by the server, it can send reconnect challenges to keep connected with the same session key.
- Client asks for a reconnection challenge with the same data as login challenge
- Server sends a reconnection challenge (16 random bytes)
- Client sends proof data with its own client proof
- Server accepts or not this proof.
To check the client proof, the server has to SHA1 the concatenation of: the account name, the proof data received, the reconnection challenge and the session key. This hash should match the client proof received to be valid.
It's worth noting that, for build 4125, the client automatically disconnect after a successful login challenge and proof exchange and sends a reconnect packet right away instead of asking for the realm list.
External resources about SRP and how to implement it:
When connecting to a realm the client starts a TCP connection to the string specified in the realm list address and then:
- The client waits for the server to send SMSG_AUTH_CHALLENGE, sending CMSG_PING every 30 seconds.
- After receiving the SMSG_AUTH_CHALLENGE the client replies with a CMSG_AUTH_SESSION.
- Packet headers are now (weakly) encrypted from now on.
- The server sends a SMSG_AUTH_RESPONSE.
- The client sends a CMSG_CHAR_ENUM.
- The server sends a SMSG_CHAR_ENUM.
The client is now on the character screen and can:
- Create a character which will send CMSG_CHAR_CREATE and the server will respond with SMSG_CHAR_CREATE. The packet is only sent after the client has entered a name and pressed "Accept".
- Delete a character which will send CMSG_CHAR_DELETE and the server will respond with SMSG_CHAR_DELETE. The packet is only sent after the client has entered "delete" and pressed "Accept".
- Rename a character which will send CMSG_CHAR_RENAME and the server will respond with SMSG_CHAR_RENAME. The packet is only sent if the rename flag is set for the character in the SMSG_CHAR_ENUM and the client tries to login.
- Request a new character list with CMSG_CHAR_ENUM and the server will respond with SMSG_CHAR_ENUM.
- Attempt to login to the world as described below.
When pressing "Enter World" the client sends a CMSG_PLAYER_LOGIN and the server responds with at least:
- An SMSG_LOGIN_VERIFY_WORLD packet that tells the client which map to load.
- An SMSG_TUTORIAL_FLAGS packet.
And then an SMSG_UPDATE_OBJECT with the player information. The player is now logged into the world and can move around the map.