Login process - drawpile/Drawpile GitHub Wiki

This document primarily documents the work-in-progress v4 protocol revision, but it mostly applies to the current version as well. (The difference between the two versions is that in v4 the messages are JSON encoded while the old protocol used a custom text based encoding.)

images/login-flowchart.png

The above diagram illustrates the login process.

ServerCommand messages are used during the login phase. The server returns three different types of replies:

  • LOGIN -- For server-push announcements (initial greeting and available sessions)
  • RESULT -- Successful command result
  • ERROR -- Command failure, will disconnect automatically

Initial handshake

When the connection is first opened, the server initiates the handshake by sending a greeting message. The greeting identifies the server as a Drawpile server and includes the protocol (server) version number and optional flags.

Possible flags are:

  • MULTI - the server can host multiple sessions
  • HOSTP - a password is needed to host new sessions (removed in 2.0)
  • TLS - the server supports TLS
  • SECURE - client MUST upgrade the connection to TLS before login can proceed
  • PERSIST - the server supports persistent sessions (i.e. sessions that are not deleted when the last user leaves)
  • IDENT - non-guest access is supported
  • NOGUEST - users MUST authenticate with a password

If the client is not compatible (mismatching server version or does not support required extensions), it must disconnect.

If the client and server both support it, TLS should be initiated. If the SECURE flag was set, the server will not let the client proceed until the connection has been upgraded. To initiate, the client sends the command STARTTLS. The server, upon receiving the command, responds with a STARTTLS of its own and calls startServerEncryption() (or the equivalent). The client starts clientside encryption when receiving the server's STARTTLS.

Greeting message format (protocol4):

{
    "type": "login",
    "version": 4,
    "flags": ["MULTI", "PERSIST", ...]
}

Identification

Before the login can proceed any further, the client must identify itself. If the IDENT flag was present, authenticated logins are possible and a password can be supplied. If NOGUEST flag was used, a password must be used.

Possible responses to an ident command are:

  • Ok: user was identified (as a guest or authenticated user)
  • Retry: Password is needed (reserved username: guest login not possible with this name)
  • Error: Password incorrect
  • Error: Invalid username
  • Error: User is banned

On succesful authentication, the user is also given a set of flags:

  • "MOD": user has moderator privileges and may log in to any (unencrypted) session, even if password protected
  • "HOST": user is allowed to host sessions (if guest hosting is disabled, this flag is needed to host)

The ident command format (protocol4):

{
    "cmd": "ident",
    "args": ["username", "password"] (password is optional)
}

Successful identification reply format (protocol 4):

{
    "type": "result",
    "state": "identOk",
    "ident": "username",
    "guest": true/false,
    "flags": ["user flags"]
}

In case a password is needed for this user:

{
    "type": "result",
    "state": "needPassword"
}

This is not a fatal error; the client can retry the ident command with the password included.

Session listing and selection

Once the client has identified itself, the server will send a list of available sessions and the server title. The server will continue to update these until the client has made a selection. A session line contains the following information:

  • ID
  • Full protocol version (must match the client's version)
  • Number of users
  • Name of the session's founder
  • Title
  • Flags
    • Session is password protected
    • Session is closed (does not accept new users at the moment)
    • Session is persistent (will not disappear when last user leaves)

The session list update message looks like this:

{
    "type": "login",
    "message: "New sessions!",
    "title": "server title",
    "sessions": [
    {
        "id": "session ID",
        "protocol": "protocol version",
        "userCount": user count,
        "founder": "user name",
        "title": "title",
        "hasPassword": true,
        "closed": true,
        "persistent": true,
        "encryption": { ... encryption settings ... }
    }, ...
    ],
    "remove": ["id 1", "id 2", ...]
}

The client can either join an existing session or host a new one.

To join a session, the client sends the join command (and the session password, if needed):

{
    "cmd": "join",
    "args": ["session ID"],
    "kwargs": {
        "password": "session password" (if needed)
    }
}

When hosting a new session, the client must provide the following:

  • Custom ID (optional. If not provided, the server will generate a random one.)
  • Protocol minor version number
  • Hosting user's ID (the client may specify this since it will upload the initial state later)
  • Hosting password (if needed)
  • Session password (v4 only)
  • Crypto settings (v4 only)

Host command:

{
    "cmd": "host",
    "kwargs": {
        "alias": "custom session ID" (optional),
        "protocol": "protocol version",
        "user_id": desired user ID (1-254),
        "password": "session password" (optional),
        "encryption": { ... encryption settings ... }
    }
}

If the join/host request was successful, the server will respond with an OK message that includes the session and user IDs assigned to the client.

{
    "type": "result",
    "state": "host" or "join",
    "join": {
        "id": "session ID",
        "user": user ID (1-255)
    }
}

Possible joining errors are:

  • No such session was found
  • Session is closed
  • Incorrect session password

Possible hosting errors are:

  • Server is full
  • Session alias already in use or invalid

Right after the login OK is message is sent, the server moves the client to the session. A newly created session starts out in an "initialization" state. The hosting client must upload the initial session snapshot to finalize the session. Until the snapshot is fully uploaded, all user input is held in a buffer. If the host logs out without finishing the initialization, the session is terminated.

The following error codes are used. Each error reply also includes a human readable error message, but the client can use the error code to display a localized message instead.

  • tlsRequired -- The server requires that TLS is used to secure the connection
  • syntax -- Command syntax error. This indicates a bug in the client software
  • badUsername -- Invalid username
  • badPassword -- Incorrect password
  • banned -- User name is banned
  • noIdent -- This is a guest-only server (never seen if the client is working as it should)
  • noGuest -- Guest logins are not allowed
  • closed -- The server or session is not accepting any more clients
  • idInUse -- Session ID already in use
  • notFound -- Specified session not found
  • nameInUse -- This username is already in use (in the selected session)
  • noTls -- TLS support not found (shouldn't happen normally)
  • alreadySecure -- Client tried to upgrade to TLS twice (bug in client)