server icon indicating copy to clipboard operation
server copied to clipboard

Implementation of the /api/v9/auth/sessions endpoints, along with storing that data

Open atvalerie opened this issue 6 months ago • 4 comments

In Discord user settings, there is an option to look at all active user sessions.

Image

The data that the client receives lives under the /api/v9/auth/sessions endpoint, which returns data that looks like this:

{
    "user_sessions": [
        {
            "id_hash": "N5XXXXXXXXXXXXXXXXXXXXXXXXXXXvQ=", // standard base64, decoding gives 32 bytes (maybe sha256)
            "approx_last_used_time": "2025-07-16T23:34:24.697588+00:00",
            "client_info": {
                "os": "Linux",
                "platform": "Discord Client",
                "location": "City, State, Country"
            }
        },
        {
            "id_hash": "5OXXXXXXXXXXXXXXXXXXXXXXXXXX/ytlhw=",
            "approx_last_used_time": "2025-07-16T23:48:20.298589+00:00",
            "client_info": {
                "os": "Linux",
                "platform": "Firefox",
                "location": "City, State, Country"
            }
        }
    ],
}

That data is stored when you log in or register on Discord, and is passed through the /api/v9/auth/login (or register) endpoint with a base64 encoded "X-Super-Properties" header.

Decoded data looks like this:

{
  "os": "Linux",
  "browser": "Firefox",
  "device": "",
  "system_locale": "en-US",
  "has_client_mods": false,
  "browser_user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0",
  "browser_version": "140.0",
  "os_version": "",
  "referrer": "",
  "referring_domain": "",
  "referrer_current": "",
  "referring_domain_current": "",
  "release_channel": "stable",
  "client_build_number": 419057,
  "client_event_source": null,
  "client_launch_id": "0e7e39d4-73b3-4c2b-b041-fea5b5a8f0b8", // random uuid replaced
  "launch_signature": "59473c7a-8cda-4895-b773-58c7c348338a", // likewise
  "client_app_state": "focused",
}

In order to implement this, maybe a new table should be made with device session information, and that device session being related to the users token when they log in, so that it can be revoked.

atvalerie avatar Jul 17 '25 00:07 atvalerie

In order to log out a specific session, a POST request to /api/v9/auth/sessions/logout is called, where you have to reauthenticate with an MFA code (or password), as the first request will return a 401. The payload of that POST request is a session ID hash of the device:

{
  "session_id_hashes": ["5OXXXXXXXXXXXXXXXXXXXXXXXXXX/ytlhw="] // this is the same as the Firefox id in the previous issue comment
}

The first response is:

{
    "message": "Two factor is required for this operation",
    "code": 60003,
    "mfa": {
        "ticket": "xxxx.xxxx.xxxx", // xxxx.xxxx.xxxx - first xxxx is your user ID, second i couldnt figure out, third i also couldnt figure out
        "methods": [
            {
                "type": "totp",
                "backup_codes_allowed": false
            }
        ]
    }
}

in case of 2FA.

And in case of a password:

{
    "message": "Two factor is required for this operation",
    "code": 60003,
    "mfa": {
        "ticket": "xxxx.xxxx.xxxx",
        "methods": [
            {
                "type": "password"
            }
        ]
    }
}

When a 2fa code is entered, there's a POST request to /api/v9/mfa/finish, the payload looks like this:

{
  "ticket": "xxxx.xxxx.xxxx", // might be the ticket from the previous request
  "mfa_type": "totp",
  "data": "" // your 2fa code
}

and a token is returned in response as a single string in a JSON object ("token": "")

The final request for logging out is another POST request to /api/v9/auth/sessions/logout, which returns a 204 if deleting something. The payload is the same as the first request. The only thing that's different is that the request contains an X-Discord-Mfa-Authorization header with the token that's returned by the /api/v9/mfa/finish response, and the discord client sends an additional cookie called __Secure-recent_mfa=token, where token is the MFA token.

atvalerie avatar Jul 17 '25 01:07 atvalerie

Additional (less needed) information: There is a button in the Devices section, which triggers a "suspicious sessions" notification. It's a POST request to /api/v9/auth/sessions/debug/notifications, however nothing is returned (404).

The tooltip of the button says "Triggers mobile and email suspicious session notifications for the current user", so if the server ever decides to save device information (or something that lets it send notifications to the user), that could be used for sending such notifications. As for initial support on Spacebar, the endpoint could just send a simple e-mail to the user, if a server is configured to send those.

atvalerie avatar Jul 17 '25 02:07 atvalerie

The tickets are in this format.

atvalerie avatar Jul 17 '25 05:07 atvalerie

https://github.com/spacebarchat/server/issues/1316 must be implemented first, before signing out devices can be added.

atvalerie avatar Jul 18 '25 20:07 atvalerie

@TheArcaneBrony hey, should this be closed?

MathMan05 avatar Dec 17 '25 22:12 MathMan05

the implementation is probably incomplete, but all the core is there (including listing and signing out devices)

TheArcaneBrony avatar Dec 18 '25 03:12 TheArcaneBrony

tbf i forgot this issue even existed lol

TheArcaneBrony avatar Dec 18 '25 03:12 TheArcaneBrony