Sauerbraten’s auth mechanism is often misunderstood. This section explains what /auth does, and how it does it.

On a vanilla server (and most modded servers), there are 3 privilege levels: “admin”, “auth” and “master” (or 4 if you count “unprivileged” as a level of privilege). admin can do everything on a server, including server configuration things like setting the server’s bot limit. admin, auth and master can do the usual gameplay stuff like change mode, map and mastermode, move players around from team to team or put them into the group of spectators, pause the game, kick people, and so on. auth is a little bit higher than master though, in that auth can kick master, but not the other way around. Also, you can only get auth privileges using the /auth command and a working auth key, while you can get master using /setmaster 1 too. Players with admin privilege are shown orange on the score board, masters are green, and players with auth are purple (but were green, just like masters, in older Sauerbraten versions).

For those looking to write a server mod: note that /auth-functionality is dictated by the master server at master.sauerbraten.org: If your server does not allow people to use their global auth keys to kick cheaters etc., your server will get banned from the master server and will no longer show up in the server browser.

What it looks like

First of all, for /auth to do anything, you need an authkey in your auth.cfg. An authkey consists of 3 parts and is used in auth.cfg like this:

authkey <name> <key> [domain/description]
  • authkey is a cubescript command which adds the key to a list of keys in memory at startup.
  • name is the name for which the key (pair) was generated.
  • key is actually the private key of a key pair. It’s a 192 bit key, represented as a 48-characters long hexadecimal string.
  • The last part is optional, and its defininition is a little blurry. The source code refers to it as desc, but domain is a more accurate name for it. More on why it is used later.

Different methods of authentication

A lot of people don’t know, but /auth can not only be used to authenticate a player globally (the game server asks the master server at master.sauerbraten.org if it recognizes the player), but also locally (the game server itself recognizes the user). This means a player can have many auth keys in their auth.cfg, and when using /auth, the game server could first try to ask for a “local” authkey. Some hopmod servers use this method. The wahnmod servers (oo, DM, PSL) did not use this method, but gave trusted users and admins their privileges after they logged in using the /setmaster "name/password" method. This method was part of their mod; in a vanilla server, /setmaster can only be used with one password (the adminpassword server variable), and gives you admin privileges (apart from /setmaster 1 of course, which gives you master privileges when allowed).

This local authentication method is also the reason why the last part of an authkey is needed, and why domain is a good word for it: the server tells the client which key to use for authenticating. When authenticating globally (at the master server, through the game server), it will tell the client to use the key with description "" (an empty string), because global auth keys do not have the last part (hence optional).

The internals

When you do /auth in your client, what actually happens is a lot more complicated than sending your key to the server. In fact, the key is never sent to the server, and it would be wrong to do so, since it is supposed to stay secret. Sending it to the server would mean the server admin could log it and use it to pretend to be you on a different server.

Instead, the auth mechanism relies on public-key cryptography. Whenever someone gives you an authkey, he has actually generated 2 keys, or a key pair, consisting of a public key and a private key. The private key is the one you get. Think of it as a key to a really strong padlock. The other part, the public key, although being called “key” is actually more like the padlock your key fits into.

The person who generated the keys will of course be able to keep the private key, too, or even give it away to someone else, but that would not be in their interest, since they generated the key pair to authenticate the player (i.e. be sure it’s them, not someone else). Global auth keys are generated by whoever currently runs master.sauerbraten.org (probably eihrul, the main developer at the moment). The master server has the public keys of all the global auth keys in existence, except those that have been revoked for abuse.

Back to /auth in your client. What happens under the hood is this (assuming the server does not use local auth, only global auth):

1. Client → I want to authenticate!                                 → Server
          ←          OK, you'll need your global auth key for that. ←
          → Found it, my name for that key is 'player1'.            →

2. Server → I need an auth challenge for 'player1', please!         → Master
          ←     Tell him to decrypt this for me: <encrypted bytes>. ←

3. Client ←                Decrypt these please: <encrypted bytes>. ← Server
          → Here you go: <decrypted bytes>.                         →

4. Server → This is what he sent me: <decrypted bytes>.             → Master
          ←                Yup, looks good. He really is 'player1'. ←

5. Client ←      OK, Master confirmed it. You have auth privileges! ← Server

Here is a detailed explanation of each of the five steps:

  1. The client asks the server for auth privileges. The server replies by telling the client the auth domain of the auth key that will be needed to authenticate (in this case, the global domain). The client checks if it has an auth key matching the domain. If it finds a fitting key, it tells the server what its “auth name” for that domain is. If it does not find one, /auth didn’t work and the process of authenticating has failed and is over.
  2. The server asks the master server to generate a challenge to pass on to the client and provides the auth name it received from the client. The master server looks for a public key belonging to that auth name. If there is none, it will tell the server, which in turn will tell the client that authentication has failed. If there is a public key matching the name, the master server then creates a challenge by encrypting a seed (basically random bytes) with the public key of player1. It also stores the seed (the unencrypted random bytes) locally.
  3. The server forwards the challenge to the client. The client decrypts the bytes it got sent using the private key. Since the clear text is random, the client doesn’t know yet if his key worked or not. Only the master server will know if the key worked.
  4. The server forwards the client’s repsonse to the master server. The master server compares the bytes he stored with the bytes the server forwarded to him. When they are the same, the client must have the correct private key, and the master server can be sure that the client trying to authenticate really is who he claims to be (unless the auth key was stolen of course…).
  5. The server now gives the client auth privileges.