Remote Auth (QR Code Login)
Remote auth lets you log into Discord on desktop by scanning a QR code on your phone.
On desktop, Discord firsts open a WebSocket connection to REMOTE_AUTH_ENDPOINT, currently wss://remote-auth-gateway.discord.gg/?v=2
Info
Unlike the normal Discord gateway, data fields do not belong to a d sub-object; all fields are at the top level, next to op. For example, the hello opcode looks like this:
{
"op": "hello",
"timeout_ms": 123456,
"heartbeat_interval": 41250
}
On open, the gateway sends opcode hello.
hello
| Field | Type | Description |
|---|---|---|
| timeout_ms | integer | milliseconds until the client should disconnect with 4003 Handshake Timeout |
| heartbeat_interval | integer | milliseconds interval for sending heartbeat ops |
When the desktop receives hello, it uses the SubtleCrypto interface to generate a 2048-bit RSA key and encodes the public key in SubjectPublicKeyInfo format.
The desktop then sends an opcode init.
init
| Field | Type | Description |
|---|---|---|
| encoded_public_key | string | base64-encoded public key |
The gateway responds with opcode nonce_proof.
nonce_proof (Server to client)
| Field | Type | Description |
|---|---|---|
| encrypted_nonce | string | base64-encoded encrypted nonce |
The desktop decrypts it with its private key using OAEP and sends back a nonce_proof.
nonce_proof (Client to server)
| Field | Type | Description |
|---|---|---|
| nonce | string | base64-encoded decrypted nonce |
The gateway responds with pending_remote_init and then the next stop involves scanning the QR code.
pending_remote_init
| Field | Type | Description |
|---|---|---|
| fingerprint | string |
The QR code is generated using the string https://discord.com/ra/{fingerprint}.
When a mobile device scans the QR code, it extracts the fingerprint from the url and makes a REMOTE_AUTH_INITIALIZE request.
REMOTE_AUTH_INITIALIZE
POST /users/@me/remote-auth
| Field | Type | Description |
|---|---|---|
| fingerprint | string | fingerprint from the QR code |
Return value:
| Field | Type | Description |
|---|---|---|
| handshake_token | string | temporary token to finalize login |
After the mobile device makes this request, the remote auth gateway sends a pending_ticket to the desktop.
pending_ticket
| Field | Type | Description |
|---|---|---|
| encrypted_user_payload | string | encrypted user payload described below |
Encrypted user payload
<user id>:<discriminator>:<avatar hash>:<username>
The mobile device then confirms the login request with a REMOTE_AUTH_FINISH request.
REMOTE_AUTH_FINISH
POST /users/@me/remote-auth/finish
| Field | Type | Description |
|---|---|---|
| handshake_token | string | token from REMOTE_AUTH_INITIALIZE |
| temporary | boolean | false |
After the mobile device sends a REMOTE_AUTH_FINISH, the gateway sends a pending_login to the desktop and the websocket is closed.
pending_login
| Field | Type | Description |
|---|---|---|
| ticket | string | ticket to use for obtaining the token |
REMOTE_AUTH_LOGIN
After getting the ticket, the desktop makes one last request to get the token
POST /users/@me/remote-auth/login
| Field | Type | Description |
|---|---|---|
| ticket | string | ticket from pending_login |
Response:
| Field | Type | Description |
|---|---|---|
| encrypted_token | string | encrypted token, decrypted like everything else |
REMOTE_AUTH_CANCEL
The mobile device can cancel a pending remote auth login by sending a REMOTE_AUTH_CANCEL. The desktop receives a cancel event.
POST /users/@me/remote-auth/cancel
| Field | Type | Description |
|---|---|---|
| handshake_token | string | token from REMOTE_AUTH_INITIALIZE |
cancel
Received when the mobile device cancels a login request. There is no extra data for this op.