Authenticate through Mojang's session server; check client version
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]>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
package org.saturnclient.client;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
/**
|
||||
* Mojang's session server "join" call, the same one vanilla makes when joining
|
||||
* an online-mode server. The access token is only ever sent to Mojang; the
|
||||
* Saturn server then confirms the join with {@code hasJoined}.
|
||||
*/
|
||||
public final class MojangSession {
|
||||
private static final URI JOIN_URI = URI.create("https://sessionserver.mojang.com/session/minecraft/join");
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
public enum JoinResult {
|
||||
JOINED,
|
||||
/** Mojang refused the access token; retrying won't help. */
|
||||
REJECTED,
|
||||
/** Network or server error; worth retrying. */
|
||||
FAILED
|
||||
}
|
||||
|
||||
private MojangSession() {
|
||||
}
|
||||
|
||||
public static JoinResult join(HttpClient http, String accessToken, UUID profile, String serverId) {
|
||||
ObjectNode body = MAPPER.createObjectNode()
|
||||
.put("accessToken", accessToken)
|
||||
.put("selectedProfile", profile.toString().replace("-", ""))
|
||||
.put("serverId", serverId);
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder(JOIN_URI)
|
||||
.timeout(Duration.ofSeconds(10))
|
||||
.header("Content-Type", "application/json")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(body.toString()))
|
||||
.build();
|
||||
|
||||
try {
|
||||
int status = http.send(request, HttpResponse.BodyHandlers.discarding()).statusCode();
|
||||
|
||||
if (status == 204 || status == 200) {
|
||||
return JoinResult.JOINED;
|
||||
}
|
||||
|
||||
return status == 401 || status == 403 ? JoinResult.REJECTED : JoinResult.FAILED;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return JoinResult.FAILED;
|
||||
} catch (Exception e) {
|
||||
return JoinResult.FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user