Authenticate through Mojang's session server; check client version #3

Merged
selimaj-dev merged 1 commits from mojang-session-auth into master 2026-09-25 13:24:47 +00:00
Owner

Client half of saturnclientmc/saturnclient#7. The server half is saturnclientmc/server#4.

Summary

Authentication (#7)

The access token only goes to Mojang now. ServiceClient's connect step:

  1. auth_challenge(username): the server returns a one-time server id.
  2. MojangSession.join(...): POST https://sessionserver.mojang.com/session/minecraft/join with the token, the undashed UUID and the server id.
    • 204 means joined.
    • 401/403 means the token was refused. The client gives up, since retrying can't help; this is also what happens for offline accounts.
    • Anything else means retry with backoff.
  3. auth_verify(): the server confirms the join with hasJoined and returns the player's data.

ServiceMethods.Authenticate is replaced by AuthChallenge and AuthVerify.

Version check

Before each connect attempt, including reconnects, the client fetches GET /versions. The URL is derived from the server URI: wss:// becomes https://, and -Dsaturn.serverUri is respected. It then compares its own mod version, without the +1.21.x build suffix:

Status Behaviour
in supported connects
in deprecated warning toast "Saturn Client update available", then connects
in neither warning toast "Saturn Client is outdated", doesn't connect
  • Warnings are shown once per status change, so reconnects don't repeat the toast.
  • If the manifest can't be fetched, the server is treated as unreachable and the client retries with backoff.
  • VersionManifest ignores unknown fields, so the server can add fields later.

Provider API

SaturnProvider gains two methods, implemented in every versions/* folder in the saturnclient PR:

  • getModVersion(), from Fabric's mod metadata
  • showWarning(title, message), a 15 s vanilla SystemToast

Testing

  • ./gradlew compileJava passes for all 8 versions, together with the saturnclient changes.
  • 1.21.11 with a real account (DevAuth) against a local server from saturnclientmc/server#4:
    • supported: the full Mojang flow. The server logged Authenticated Kr4ight.
    • deprecated: logged "0.1.0-beta3 is deprecated", then connected and authenticated. This was triggered by restarting the server with a new manifest while the client was running, which also exercises reconnect.
    • unsupported: logged "no longer supported, not connecting". The server saw no WebSocket connection, and the client didn't retry.
    • The toast was queued in the running game in both warning cases, with no exceptions or render-thread errors.
  • Not verified: how the toast looks (macOS kept the relaunched test client stuck in glfwInit, before mod code), and the offline-account path.

Merge order

Merge this first. The saturnclient PR, with the provider implementations and the mod_version bump to 0.1.0-beta3, will be opened against this PR's merge commit.

🤖 Generated with Claude Code

Client half of saturnclientmc/saturnclient#7. The server half is saturnclientmc/server#4. ## Summary ### Authentication (#7) The access token **only goes to Mojang** now. `ServiceClient`'s connect step: 1. `auth_challenge(username)`: the server returns a one-time server id. 2. `MojangSession.join(...)`: `POST https://sessionserver.mojang.com/session/minecraft/join` with the token, the undashed UUID and the server id. - `204` means joined. - `401`/`403` means the token was refused. The client **gives up**, since retrying can't help; this is also what happens for offline accounts. - Anything else means retry with backoff. 3. `auth_verify()`: the server confirms the join with `hasJoined` and returns the player's data. `ServiceMethods.Authenticate` is replaced by `AuthChallenge` and `AuthVerify`. ### Version check Before each connect attempt, including reconnects, the client fetches `GET /versions`. The URL is derived from the server URI: `wss://` becomes `https://`, and `-Dsaturn.serverUri` is respected. It then compares its own mod version, without the `+1.21.x` build suffix: | Status | Behaviour | | --- | --- | | in `supported` | connects | | in `deprecated` | warning toast "Saturn Client update available", then connects | | in neither | warning toast "Saturn Client is outdated", **doesn't connect** | - Warnings are shown once per status change, so reconnects don't repeat the toast. - If the manifest can't be fetched, the server is treated as unreachable and the client retries with backoff. - `VersionManifest` ignores unknown fields, so the server can add fields later. ### Provider API `SaturnProvider` gains two methods, implemented in every `versions/*` folder in the saturnclient PR: - `getModVersion()`, from Fabric's mod metadata - `showWarning(title, message)`, a 15 s vanilla `SystemToast` ## Testing - `./gradlew compileJava` passes for all 8 versions, together with the saturnclient changes. - 1.21.11 with a real account (DevAuth) against a local server from saturnclientmc/server#4: - **supported:** the full Mojang flow. The server logged `Authenticated Kr4ight`. - **deprecated:** logged "0.1.0-beta3 is deprecated", then connected and authenticated. This was triggered by restarting the server with a new manifest while the client was running, which also exercises reconnect. - **unsupported:** logged "no longer supported, not connecting". The server saw no WebSocket connection, and the client didn't retry. - The toast was queued in the running game in both warning cases, with no exceptions or render-thread errors. - **Not verified:** how the toast looks (macOS kept the relaunched test client stuck in `glfwInit`, before mod code), and the offline-account path. ## Merge order Merge this first. The saturnclient PR, with the provider implementations and the `mod_version` bump to `0.1.0-beta3`, will be opened against this PR's merge commit. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
selimaj-dev added 1 commit 2026-09-25 13:22:39 +00:00
Stop sending the Minecraft access token to the Saturn server. The
connect loop now:

1. fetches GET /versions and compares this client's mod version:
   supported -> connect; deprecated -> warn, connect; neither -> warn,
   don't connect (warnings are shown once per status change)
2. requests auth_challenge with the username to get a server id
3. calls Mojang's session `join` with the access token and server id
   (the token only goes to Mojang); a refused token gives up
4. requests auth_verify, which the server confirms with `hasJoined`

Add SaturnProvider.getModVersion() and showWarning() for the version
check and its toast.

Refs saturnclientmc/saturnclient#7

Co-Authored-By: Claude Opus 5.5 <[email protected]>
selimaj-dev merged commit 98da42992e into master 2026-09-25 13:24:47 +00:00
selimaj-dev deleted branch mojang-session-auth 2026-09-25 13:24:50 +00:00
Sign in to join this conversation.