Stop sending the Minecraft access token to the Saturn server #7

Closed
opened 2026-09-25 11:43:41 +00:00 by selimaj-dev · 0 comments
Owner

Problem

The auth RPC sends the player's Minecraft access token to the Saturn server. The server calls api.minecraftservices.com/minecraft/profile with it to learn the player's UUID and name (server/src/methods/auth.rs).

That token grants full access to the player's Minecraft account. The Saturn server never needs it, but it currently receives every user's token. If the server, its logs or the path to it were ever compromised, every Saturn user's account would be exposed.

Proposed fix

Use Mojang's standard session flow, the one vanilla servers use, so the token never leaves the client:

  1. The server sends the client a random serverId challenge.
  2. The client calls POST https://sessionserver.mojang.com/session/minecraft/join with its token, UUID and the serverId. The token only goes to Mojang.
  3. The client tells the server it has joined.
  4. The server calls GET https://sessionserver.mojang.com/session/minecraft/hasJoined?username=<name>&serverId=<id> and gets the verified profile (UUID and name).

Rollout

This changes the protocol, so it needs a coordinated release:

  • add new methods (e.g. auth_challenge, auth_verify) on the server while keeping the old auth working for clients already released
  • ship a client release that uses the new flow
  • remove the old auth once old clients have aged out
## Problem The `auth` RPC sends the player's **Minecraft access token** to the Saturn server. The server calls `api.minecraftservices.com/minecraft/profile` with it to learn the player's UUID and name (`server/src/methods/auth.rs`). That token grants full access to the player's Minecraft account. The Saturn server never needs it, but it currently receives every user's token. If the server, its logs or the path to it were ever compromised, every Saturn user's account would be exposed. ## Proposed fix Use Mojang's standard session flow, the one vanilla servers use, so the token never leaves the client: 1. The server sends the client a random `serverId` challenge. 2. The client calls `POST https://sessionserver.mojang.com/session/minecraft/join` with its token, UUID and the `serverId`. The token only goes to Mojang. 3. The client tells the server it has joined. 4. The server calls `GET https://sessionserver.mojang.com/session/minecraft/hasJoined?username=<name>&serverId=<id>` and gets the verified profile (UUID and name). ## Rollout This changes the protocol, so it needs a coordinated release: - add new methods (e.g. `auth_challenge`, `auth_verify`) on the server while keeping the old `auth` working for clients already released - ship a client release that uses the new flow - remove the old `auth` once old clients have aged out
Sign in to join this conversation.