Skip to content

Commit 48bf094

Browse files
authored
Updated to MinecraftAuth 5 (#5989)
1 parent a58fa79 commit 48bf094

File tree

6 files changed

+46
-95
lines changed

6 files changed

+46
-95
lines changed

core/src/main/java/org/geysermc/geyser/GeyserImpl.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import lombok.Setter;
3939
import net.kyori.adventure.text.Component;
4040
import net.kyori.adventure.text.format.NamedTextColor;
41+
import net.raphimc.minecraftauth.msa.data.MsaConstants;
42+
import net.raphimc.minecraftauth.msa.model.MsaApplicationConfig;
4143
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
4244
import org.checkerframework.checker.nullness.qual.NonNull;
4345
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -145,9 +147,9 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
145147
public static final boolean IS_DEV = BuildData.isDevBuild();
146148

147149
/**
148-
* Oauth client ID for Microsoft authentication
150+
* Oauth config for Microsoft authentication
149151
*/
150-
public static final String OAUTH_CLIENT_ID = "204cefd1-4818-4de1-b98d-513fae875d88";
152+
public static final MsaApplicationConfig OAUTH_CONFIG = new MsaApplicationConfig("204cefd1-4818-4de1-b98d-513fae875d88", MsaConstants.SCOPE_OFFLINE_ACCESS);
151153

152154
private static final Pattern IP_REGEX = Pattern.compile("\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b");
153155

core/src/main/java/org/geysermc/geyser/session/GeyserSession.java

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@
4141
import lombok.experimental.Accessors;
4242
import net.kyori.adventure.key.Key;
4343
import net.kyori.adventure.text.Component;
44-
import net.raphimc.minecraftauth.responsehandler.exception.MinecraftRequestException;
45-
import net.raphimc.minecraftauth.step.java.StepMCProfile;
46-
import net.raphimc.minecraftauth.step.java.StepMCToken;
47-
import net.raphimc.minecraftauth.step.java.session.StepFullJavaSession;
44+
import net.raphimc.minecraftauth.java.JavaAuthManager;
45+
import net.raphimc.minecraftauth.java.exception.MinecraftProfileNotFoundException;
46+
import net.raphimc.minecraftauth.java.model.MinecraftProfile;
47+
import net.raphimc.minecraftauth.java.model.MinecraftToken;
48+
import net.raphimc.minecraftauth.util.MinecraftAuth4To5Migrator;
4849
import org.checkerframework.checker.index.qual.NonNegative;
4950
import org.checkerframework.checker.index.qual.Positive;
5051
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@@ -113,7 +114,6 @@
113114
import org.geysermc.geyser.GeyserImpl;
114115
import org.geysermc.geyser.api.bedrock.camera.CameraData;
115116
import org.geysermc.geyser.api.bedrock.camera.CameraShake;
116-
import org.geysermc.geyser.input.InputLocksFlag;
117117
import org.geysermc.geyser.api.connection.GeyserConnection;
118118
import org.geysermc.geyser.api.entity.EntityData;
119119
import org.geysermc.geyser.api.entity.type.GeyserEntity;
@@ -143,6 +143,7 @@
143143
import org.geysermc.geyser.event.type.SessionDisconnectEventImpl;
144144
import org.geysermc.geyser.impl.camera.CameraDefinitions;
145145
import org.geysermc.geyser.impl.camera.GeyserCameraData;
146+
import org.geysermc.geyser.input.InputLocksFlag;
146147
import org.geysermc.geyser.inventory.Inventory;
147148
import org.geysermc.geyser.inventory.InventoryHolder;
148149
import org.geysermc.geyser.inventory.LecternContainer;
@@ -196,7 +197,6 @@
196197
import org.geysermc.geyser.util.InventoryUtils;
197198
import org.geysermc.geyser.util.LoginEncryptionUtils;
198199
import org.geysermc.geyser.util.MathUtils;
199-
import org.geysermc.geyser.util.MinecraftAuthLogger;
200200
import org.geysermc.mcprotocollib.auth.GameProfile;
201201
import org.geysermc.mcprotocollib.network.BuiltinFlags;
202202
import org.geysermc.mcprotocollib.network.ClientSession;
@@ -925,23 +925,28 @@ public void authenticateWithAuthChain(String authChain) {
925925
loggingIn = true;
926926

927927
CompletableFuture.supplyAsync(() -> {
928-
StepFullJavaSession step = PendingMicrosoftAuthentication.AUTH_FLOW.apply(true, 30);
929-
StepFullJavaSession.FullJavaSession response;
928+
JavaAuthManager authManager;
929+
MinecraftProfile mcProfile;
930+
MinecraftToken mcToken;
930931
try {
931-
response = step.refresh(MinecraftAuthLogger.INSTANCE, PendingMicrosoftAuthentication.AUTH_CLIENT, step.fromJson(GSON.fromJson(authChain, JsonObject.class)));
932+
JsonObject parsedAuthChain = GSON.fromJson(authChain, JsonObject.class);
933+
if (parsedAuthChain.has("mcProfile")) { // Old Minecraft v4 auth chain
934+
parsedAuthChain = MinecraftAuth4To5Migrator.migrateJavaSave(parsedAuthChain, GeyserImpl.OAUTH_CONFIG);
935+
}
936+
937+
authManager = JavaAuthManager.fromJson(PendingMicrosoftAuthentication.AUTH_CLIENT, parsedAuthChain);
938+
mcProfile = authManager.getMinecraftProfile().getUpToDate();
939+
mcToken = authManager.getMinecraftToken().getUpToDate();
932940
} catch (Exception e) {
933941
geyser.getLogger().error("Error while attempting to use auth chain for " + bedrockUsername() + "!", e);
934942
return Boolean.FALSE;
935943
}
936944

937-
StepMCProfile.MCProfile mcProfile = response.getMcProfile();
938-
StepMCToken.MCToken mcToken = mcProfile.getMcToken();
939-
940945
protocol = new MinecraftProtocol(
941946
new GameProfile(mcProfile.getId(), mcProfile.getName()),
942-
mcToken.getAccessToken()
947+
mcToken.getToken()
943948
);
944-
geyser.saveAuthChain(bedrockUsername(), GSON.toJson(step.toJson(response)));
949+
geyser.saveAuthChain(bedrockUsername(), GSON.toJson(JavaAuthManager.toJson(authManager)));
945950
return Boolean.TRUE;
946951
}).whenComplete((successful, ex) -> {
947952
if (this.closed) {
@@ -1009,9 +1014,7 @@ public boolean onMicrosoftLoginComplete(PendingMicrosoftAuthentication.Authentic
10091014
return task.getAuthentication().handle((result, ex) -> {
10101015
if (ex != null) {
10111016
geyser.getLogger().error("Failed to log in with Microsoft code!", ex);
1012-
if (ex instanceof CompletionException ce
1013-
&& ce.getCause() instanceof MinecraftRequestException mre
1014-
&& mre.getResponse().getStatusCode() == 404) {
1017+
if (ex instanceof CompletionException ce && ce.getCause() instanceof MinecraftProfileNotFoundException) {
10151018
// Player is trying to join with a Microsoft account that doesn't have Java Edition purchased
10161019
disconnect(GeyserLocale.getPlayerLocaleString("geyser.network.remote.invalid_account", locale()));
10171020
} else {
@@ -1020,12 +1023,12 @@ public boolean onMicrosoftLoginComplete(PendingMicrosoftAuthentication.Authentic
10201023
return false;
10211024
}
10221025

1023-
StepMCProfile.MCProfile mcProfile = result.session().getMcProfile();
1024-
StepMCToken.MCToken mcToken = mcProfile.getMcToken();
1026+
MinecraftProfile mcProfile = result.getMinecraftProfile().getCached();
1027+
MinecraftToken mcToken = result.getMinecraftToken().getCached();
10251028

10261029
this.protocol = new MinecraftProtocol(
10271030
new GameProfile(mcProfile.getId(), mcProfile.getName()),
1028-
mcToken.getAccessToken()
1031+
mcToken.getToken()
10291032
);
10301033

10311034
try {
@@ -1036,7 +1039,7 @@ public boolean onMicrosoftLoginComplete(PendingMicrosoftAuthentication.Authentic
10361039
}
10371040

10381041
// Save our auth chain for later use
1039-
geyser.saveAuthChain(bedrockUsername(), GSON.toJson(result.step().toJson(result.session())));
1042+
geyser.saveAuthChain(bedrockUsername(), GSON.toJson(JavaAuthManager.toJson(result)));
10401043
return true;
10411044
}).getNow(false);
10421045
}

core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,21 @@
3333
import lombok.SneakyThrows;
3434
import net.lenni0451.commons.httpclient.HttpClient;
3535
import net.raphimc.minecraftauth.MinecraftAuth;
36-
import net.raphimc.minecraftauth.step.java.session.StepFullJavaSession;
37-
import net.raphimc.minecraftauth.step.msa.StepMsaDeviceCode;
38-
import net.raphimc.minecraftauth.util.MicrosoftConstants;
36+
import net.raphimc.minecraftauth.java.JavaAuthManager;
37+
import net.raphimc.minecraftauth.msa.data.MsaConstants;
38+
import net.raphimc.minecraftauth.msa.model.MsaApplicationConfig;
39+
import net.raphimc.minecraftauth.msa.model.MsaDeviceCode;
40+
import net.raphimc.minecraftauth.msa.model.MsaToken;
41+
import net.raphimc.minecraftauth.msa.service.impl.DeviceCodeMsaAuthService;
3942
import org.checkerframework.checker.nullness.qual.NonNull;
4043
import org.geysermc.geyser.GeyserImpl;
4144
import org.geysermc.geyser.GeyserLogger;
42-
import org.geysermc.geyser.util.MinecraftAuthLogger;
4345

4446
import java.util.concurrent.CompletableFuture;
4547
import java.util.concurrent.CompletionException;
4648
import java.util.concurrent.ExecutionException;
4749
import java.util.concurrent.Executor;
4850
import java.util.concurrent.TimeUnit;
49-
import java.util.function.BiFunction;
5051
import java.util.function.Consumer;
5152

5253
/**
@@ -55,14 +56,6 @@
5556
*/
5657
public class PendingMicrosoftAuthentication {
5758
public static final HttpClient AUTH_CLIENT = MinecraftAuth.createHttpClient();
58-
public static final BiFunction<Boolean, Integer, StepFullJavaSession> AUTH_FLOW = (offlineAccess, timeoutSec) -> MinecraftAuth.builder()
59-
.withClientId(GeyserImpl.OAUTH_CLIENT_ID)
60-
.withScope(offlineAccess ? "XboxLive.signin XboxLive.offline_access" : "XboxLive.signin")
61-
.withTimeout(timeoutSec)
62-
.deviceCode()
63-
.withoutDeviceToken()
64-
.regularAuthentication(MicrosoftConstants.JAVA_XSTS_RELYING_PARTY)
65-
.buildMinecraftJavaProfileStep(false);
6659
/**
6760
* For GeyserConnect usage.
6861
*/
@@ -100,7 +93,7 @@ public class AuthenticationTask {
10093
private final String userKey;
10194
private final int timeoutSec;
10295
@Getter
103-
private CompletableFuture<StepChainResult> authentication;
96+
private CompletableFuture<JavaAuthManager> authentication;
10497

10598
private AuthenticationTask(String userKey, int timeoutSec) {
10699
this.userKey = userKey;
@@ -124,11 +117,16 @@ public void cleanup() {
124117
authentications.invalidate(userKey);
125118
}
126119

127-
public CompletableFuture<StepChainResult> performLoginAttempt(boolean offlineAccess, Consumer<StepMsaDeviceCode.MsaDeviceCode> deviceCodeConsumer) {
120+
public CompletableFuture<JavaAuthManager> performLoginAttempt(boolean offlineAccess, Consumer<MsaDeviceCode> deviceCodeConsumer) {
121+
MsaApplicationConfig applicationConfig = GeyserImpl.OAUTH_CONFIG.withScope(offlineAccess ? MsaConstants.SCOPE_OFFLINE_ACCESS : MsaConstants.SCOPE_NO_OFFLINE_ACCESS);
122+
DeviceCodeMsaAuthService authService = new DeviceCodeMsaAuthService(AUTH_CLIENT, applicationConfig, deviceCodeConsumer, timeoutSec * 1000);
128123
return authentication = CompletableFuture.supplyAsync(() -> {
129124
try {
130-
StepFullJavaSession step = AUTH_FLOW.apply(offlineAccess, timeoutSec);
131-
return new StepChainResult(step, step.getFromInput(MinecraftAuthLogger.INSTANCE, AUTH_CLIENT, new StepMsaDeviceCode.MsaDeviceCodeCallback(deviceCodeConsumer)));
125+
MsaToken msaToken = authService.acquireToken();
126+
JavaAuthManager authManager = JavaAuthManager.create(AUTH_CLIENT).msaApplicationConfig(applicationConfig).login(msaToken);
127+
authManager.getMinecraftToken().refresh(); // Preload the Minecraft token
128+
authManager.getMinecraftProfile().refresh(); // Preload the Minecraft profile
129+
return authManager;
132130
} catch (Exception e) {
133131
throw new CompletionException(e);
134132
}
@@ -154,7 +152,4 @@ private ProxyAuthenticationTask(String userKey, int timeoutSec) {
154152
super(userKey, timeoutSec);
155153
}
156154
}
157-
158-
public record StepChainResult(StepFullJavaSession step, StepFullJavaSession.FullJavaSession session) {
159-
}
160155
}

core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import com.fasterxml.jackson.databind.DeserializationFeature;
2929
import com.fasterxml.jackson.databind.JsonNode;
3030
import com.fasterxml.jackson.databind.ObjectMapper;
31-
import net.raphimc.minecraftauth.step.msa.StepMsaDeviceCode;
31+
import net.raphimc.minecraftauth.msa.model.MsaDeviceCode;
3232
import org.cloudburstmc.protocol.bedrock.data.auth.AuthPayload;
3333
import org.cloudburstmc.protocol.bedrock.data.auth.CertificateChainPayload;
3434
import org.cloudburstmc.protocol.bedrock.data.auth.TokenPayload;
@@ -215,7 +215,7 @@ private static BiConsumer<SimpleForm, FormResponseResult<SimpleFormResponse>> au
215215
/**
216216
* Shows the code that a user must input into their browser
217217
*/
218-
public static void buildAndShowMicrosoftCodeWindow(GeyserSession session, StepMsaDeviceCode.MsaDeviceCode msCode) {
218+
public static void buildAndShowMicrosoftCodeWindow(GeyserSession session, MsaDeviceCode msCode) {
219219
String locale = session.locale();
220220

221221
StringBuilder message = new StringBuilder("%xbox.signin.website\n")

core/src/main/java/org/geysermc/geyser/util/MinecraftAuthLogger.java

Lines changed: 0 additions & 49 deletions
This file was deleted.

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ protocol-connection = "3.0.0.Beta10-20251014.180344-2"
1313
protocol-common = "3.0.0.Beta10-20251014.180344-2"
1414
protocol-codec = "3.0.0.Beta10-20251014.180344-2"
1515
raknet = "1.0.0.CR3-20250811.214335-20"
16-
minecraftauth = "4.1.1"
16+
minecraftauth = "5.0.0"
1717
mcprotocollib = "1.21.9-20251029.184056-18"
1818
adventure = "4.25.0"
1919
adventure-platform = "4.4.1"

0 commit comments

Comments
 (0)