Skip to content

Add MS Java access-token & cookies auth services#950

Closed
FoxYolk wants to merge 1 commit intoAlexProgrammerDE:mainfrom
FoxYolk:main
Closed

Add MS Java access-token & cookies auth services#950
FoxYolk wants to merge 1 commit intoAlexProgrammerDE:mainfrom
FoxYolk:main

Conversation

@FoxYolk
Copy link

@FoxYolk FoxYolk commented Feb 25, 2026

Add support for importing Microsoft Java accounts via raw Minecraft access tokens and browser cookies. Introduces MSJavaAccessTokenAuthService (access-token-only auth, non-refreshable) and MSJavaCookiesAuthService (exchanges login.live.com cookies for a refresh token), and extends MSJavaRefreshTokenAuthService with cookie-import helpers/validation. Update MCAuthService to include new service variants and conversion logic, and extend AuthType/proto enums to expose MICROSOFT_JAVA_ACCESS_TOKEN and MICROSOFT_JAVA_COOKIES. OnlineChainJavaData gains helpers to detect/access access-token-only accounts. InstanceManager, SFSessionService and BotConnection are adjusted to handle non-refreshable access-token accounts and to skip expired auth. Also: javadoc Gradle task fixes (classpath + delombok ordering and configuration cache note), .gitignore additions for local artifacts, add start.bat helper, and include a bundled JavaAuthManager.class binary. Protobuf messages updated for new credential/service types.

Add support for importing Microsoft Java accounts via raw Minecraft access tokens and browser cookies. Introduces MSJavaAccessTokenAuthService (access-token-only auth, non-refreshable) and MSJavaCookiesAuthService (exchanges login.live.com cookies for a refresh token), and extends MSJavaRefreshTokenAuthService with cookie-import helpers/validation. Update MCAuthService to include new service variants and conversion logic, and extend AuthType/proto enums to expose MICROSOFT_JAVA_ACCESS_TOKEN and MICROSOFT_JAVA_COOKIES. OnlineChainJavaData gains helpers to detect/access access-token-only accounts. InstanceManager, SFSessionService and BotConnection are adjusted to handle non-refreshable access-token accounts and to skip expired auth. Also: javadoc Gradle task fixes (classpath + delombok ordering and configuration cache note), .gitignore additions for local artifacts, add start.bat helper, and include a bundled JavaAuthManager.class binary. Protobuf messages updated for new credential/service types.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds new Microsoft Java Edition authentication import paths—supporting raw Minecraft access tokens and browser cookie imports—and updates server/runtime logic to handle non-refreshable accounts and skip expired credentials.

Changes:

  • Introduces MSJavaAccessTokenAuthService (non-refreshable) and MSJavaCookiesAuthService (cookie-to-refresh-token exchange), plus enum/proto exposure for new credential types.
  • Updates session/join + instance lifecycle to use a unified “get access token” helper and to skip/avoid expired non-refreshable accounts.
  • Adjusts Javadoc Gradle task wiring and updates .gitignore/startup helpers; also adds several workspace/binary artifacts to the repo.

Reviewed changes

Copilot reviewed 15 out of 19 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
untracked8.txt Adds a local workspace artifact list (should not be committed).
untracked.txt Same as above but with encoding corruption (should not be committed).
builder.txt Appears to be a generated bytecode/javap dump (should not be committed).
start.bat Windows helper to build/find and run the dedicated launcher jar.
.gitignore Ignores downloaded libs, local runtime data, sqlite DBs, and secrets.
proto/src/main/proto/soulfire/mc-auth.proto Documents cookie-import payload for credentials auth request.
proto/src/main/proto/soulfire/common.proto Adds new credential enum values + access-token account type.
mod/src/main/java/com/soulfiremc/server/grpc/MCAuthServiceImpl.java Rejects UNRECOGNIZED auth enums to catch version mismatches early.
mod/src/main/java/com/soulfiremc/server/bot/SFSessionService.java Uses service-based expiry check and access-token retrieval for join.
mod/src/main/java/com/soulfiremc/server/bot/BotConnection.java Uses OnlineChainJavaData.getAccessToken(...) for Minecraft copy creation.
mod/src/main/java/com/soulfiremc/server/account/service/OnlineChainJavaData.java Adds access-token-only mode + access-token retrieval helper.
mod/src/main/java/com/soulfiremc/server/account/MSJavaRefreshTokenAuthService.java Adds refresh-token input validation and (currently unused) cookie helpers.
mod/src/main/java/com/soulfiremc/server/account/MSJavaCookiesAuthService.java New cookie import service exchanging cookies for a refresh token.
mod/src/main/java/com/soulfiremc/server/account/MSJavaAccessTokenAuthService.java New access-token-only auth service and expiry detection via JWT exp.
mod/src/main/java/com/soulfiremc/server/account/MCAuthService.java Adds new service variants to sealed interface + conversion logic.
mod/src/main/java/com/soulfiremc/server/account/AuthType.java Adds MICROSOFT_JAVA_ACCESS_TOKEN auth type.
mod/src/main/java/com/soulfiremc/server/InstanceManager.java Handles non-refreshable accounts and skips expired non-refreshable auth.
javadoc/build.gradle.kts Updates aggregate Javadoc deps/classpath and delombok ordering; disables config cache.
net/raphimc/minecraftauth/java/JavaAuthManager.class Adds a compiled .class into the repo (problematic).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +47 to +51
@Override
public CompletableFuture<MinecraftAccount> login(MSJavaAccessTokenAuthData data, @Nullable SFProxy proxyData, Executor executor) {
return CompletableFuture.supplyAsync(() -> {
try {
var profileJson = fetchProfile(data.accessToken);
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

proxyData is accepted by login(...) but never used (the profile request uses a raw HttpURLConnection). This breaks the existing "use proxies for account auth" behavior for access-token imports; consider using the project’s HTTP helpers (e.g., ReactorHttpHelper/LenniHttpHelper) so proxy settings and shared defaults are honored.

Suggested change
@Override
public CompletableFuture<MinecraftAccount> login(MSJavaAccessTokenAuthData data, @Nullable SFProxy proxyData, Executor executor) {
return CompletableFuture.supplyAsync(() -> {
try {
var profileJson = fetchProfile(data.accessToken);
private JsonObject fetchProfile(String accessToken, @Nullable SFProxy proxyData) throws Exception {
// Delegate to the existing implementation for now; proxyData is threaded through
// so that proxy-aware logic can be implemented here without changing callers.
return fetchProfile(accessToken);
}
@Override
public CompletableFuture<MinecraftAccount> login(MSJavaAccessTokenAuthData data, @Nullable SFProxy proxyData, Executor executor) {
return CompletableFuture.supplyAsync(() -> {
try {
var profileJson = fetchProfile(data.accessToken, proxyData);

Copilot uses AI. Check for mistakes.
Comment on lines +91 to +106
var statusCode = connection.getResponseCode();
if (statusCode != 200) {
// Try to read error body for better diagnostics
var errorStream = connection.getErrorStream();
var errorBody = "";
if (errorStream != null) {
try (var reader = new BufferedReader(new InputStreamReader(errorStream, StandardCharsets.UTF_8))) {
errorBody = reader.lines().collect(Collectors.joining("\n"));
}
}
throw new IllegalStateException("Failed to fetch Minecraft profile: HTTP " + statusCode + " " + errorBody);
}

try (var reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
var body = reader.lines().collect(Collectors.joining("\n"));
return GsonInstance.GSON.fromJson(body, JsonObject.class);
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

connection.disconnect() is only executed on the success path; if statusCode != 200 this method throws before reaching the finally, leaving the HttpURLConnection open. Wrap the whole request/response handling in a try/finally (or disconnect in the error branch) so the connection is always cleaned up.

Suggested change
var statusCode = connection.getResponseCode();
if (statusCode != 200) {
// Try to read error body for better diagnostics
var errorStream = connection.getErrorStream();
var errorBody = "";
if (errorStream != null) {
try (var reader = new BufferedReader(new InputStreamReader(errorStream, StandardCharsets.UTF_8))) {
errorBody = reader.lines().collect(Collectors.joining("\n"));
}
}
throw new IllegalStateException("Failed to fetch Minecraft profile: HTTP " + statusCode + " " + errorBody);
}
try (var reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
var body = reader.lines().collect(Collectors.joining("\n"));
return GsonInstance.GSON.fromJson(body, JsonObject.class);
try {
var statusCode = connection.getResponseCode();
if (statusCode != 200) {
// Try to read error body for better diagnostics
var errorStream = connection.getErrorStream();
var errorBody = "";
if (errorStream != null) {
try (var reader = new BufferedReader(new InputStreamReader(errorStream, StandardCharsets.UTF_8))) {
errorBody = reader.lines().collect(Collectors.joining("\n"));
}
}
throw new IllegalStateException("Failed to fetch Minecraft profile: HTTP " + statusCode + " " + errorBody);
}
try (var reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
var body = reader.lines().collect(Collectors.joining("\n"));
return GsonInstance.GSON.fromJson(body, JsonObject.class);
}

Copilot uses AI. Check for mistakes.

@Override
public MSJavaAccessTokenAuthData createData(String data) {
return new MSJavaAccessTokenAuthData(data.strip());
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createData accepts an empty/blank access token (after strip()), which will later fail with a less actionable HTTP error. Consider validating non-empty input (and possibly rejecting obvious cookie/refresh-token formats) to give callers a clear IllegalArgumentException early.

Suggested change
return new MSJavaAccessTokenAuthData(data.strip());
var stripped = data.strip();
if (stripped.isEmpty()) {
throw new IllegalArgumentException("Access token must not be empty or blank");
}
return new MSJavaAccessTokenAuthData(stripped);

Copilot uses AI. Check for mistakes.
Comment on lines +164 to +176
private static String exchangeCookieInputForRefreshToken(String cookieInput, @Nullable SFProxy proxyData) {
var cookieHeader = cookieInputToCookieHeader(cookieInput);
var authorizeUri = URI.create(
"https://login.live.com/oauth20_authorize.srf"
+ "?client_id=" + urlEncode(CLIENT_ID)
+ "&response_type=code"
+ "&response_mode=query"
+ "&redirect_uri=" + urlEncode(REDIRECT_URI)
+ "&scope=" + urlEncode(SCOPE)
+ "&prompt=none"
);

var location = ReactorHttpHelper.createReactorClient(proxyData, false)
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exchangeCookieInputForRefreshToken(...) (and the associated cookie parsing/exchange helpers below) is currently unused in this class (only declared, never called). If cookie-import is meant to be supported via MSJavaCookiesAuthService, consider removing this dead code or extracting shared cookie parsing/exchange logic into a reusable utility to avoid duplication.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +5
config/spark/tmp-client/about.txt
libraries/HdrHistogram-2.2.2.jar
libraries/HikariCP-7.0.2.jar
libraries/Java-WebSocket-1.6.0.jar
libraries/LambdaEvents-2.4.2.jar
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These look like a local git status/workspace artifact list (including paths like secret-key.bin, downloaded jars, etc.) and shouldn’t be committed to the repo. Please remove this file from the PR and rely on .gitignore for ignoring local artifacts.

Copilot uses AI. Check for mistakes.
@AlexProgrammerDE
Copy link
Owner

Thanks for the PR. I've reimplemented this now manuyll.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants