Skip to content

Commit

Permalink
Merge pull request #27 from unmojang/evan-goode/legacy
Browse files Browse the repository at this point in the history
Support authlib-injector accounts on legacy versions
  • Loading branch information
evan-goode authored Sep 6, 2024
2 parents 26a70d7 + c68ed20 commit 9bc27cb
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 24 deletions.
2 changes: 1 addition & 1 deletion launcher/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings->registerSetting("IgnoreJavaWizard", false);

// Legacy settings
m_settings->registerSetting("OnlineFixes", false);
m_settings->registerSetting("OnlineFixes", true);

// Native library workarounds
m_settings->registerSetting("UseNativeOpenAL", false);
Expand Down
5 changes: 2 additions & 3 deletions launcher/LaunchController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,8 @@ void LaunchController::login()
return;
}

if (m_accountToUse->usesCustomApiServers()) {
MinecraftInstancePtr inst = std::dynamic_pointer_cast<MinecraftInstance>(m_instance);

MinecraftInstancePtr inst = std::dynamic_pointer_cast<MinecraftInstance>(m_instance);
if (m_accountToUse->usesCustomApiServers() && !inst->shouldApplyOnlineFixes()) {
bool authlibInjectorInstalled = false;
const auto& agents = inst->getPackProfile()->getProfile()->getAgents();
for (const auto& agent : agents) {
Expand Down
1 change: 1 addition & 0 deletions libraries/launcher/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(LEGACY_SRC
legacy/org/prismlauncher/legacy/fix/online/OnlineModeFix.java
legacy/org/prismlauncher/legacy/fix/online/SkinFix.java
legacy/org/prismlauncher/legacy/utils/Base64.java
legacy/org/prismlauncher/legacy/utils/api/ApiServers.java
legacy/org/prismlauncher/legacy/utils/api/MojangApi.java
legacy/org/prismlauncher/legacy/utils/api/Texture.java
legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,80 @@

package org.prismlauncher.legacy.fix.online;

import org.prismlauncher.legacy.utils.api.ApiServers;
import org.prismlauncher.legacy.utils.api.MojangApi;
import org.prismlauncher.legacy.utils.url.ByteArrayUrlConnection;
import org.prismlauncher.legacy.utils.url.UrlUtils;

import java.io.IOException;
import java.net.MalformedURLException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

public final class OnlineModeFix {
public static URLConnection openConnection(URL address, Proxy proxy) throws IOException {
// we start with "http://www.minecraft.net/game/joinserver.jsp?user=..."
if (!(address.getHost().equals("www.minecraft.net") && address.getPath().equals("/game/joinserver.jsp")))
if (!(address.getHost().equals("www.minecraft.net") && address.getPath().equals("/game/joinserver.jsp"))) {
return null;
}

Map<String, String> params = new HashMap<>();
String query = address.getQuery();
String[] entries = query.split("&");
for (String entry : entries) {
String[] pair = entry.split("=");
if (pair.length == 2) {
params.put(pair[0], pair[1]);
}
}

// change it to "https://session.minecraft.net/game/joinserver.jsp?user=..."
// this seems to be the modern version of the same endpoint...
// maybe Mojang planned to patch old versions of the game to use it
// if it ever disappears this should be changed to use sessionserver.mojang.com/session/minecraft/join
// which of course has a different usage requiring JSON serialisation...
URL url;
try {
url = new URL("https", "session.minecraft.net", address.getPort(), address.getFile());
} catch (MalformedURLException e) {
throw new AssertionError("url should be valid", e);
String user = params.get("user");
if (user == null) {
throw new AssertionError("missing user");
}
String serverId = params.get("serverId");
if (serverId == null) {
throw new AssertionError("missing serverId");
}
String sessionId = params.get("sessionId");
if (sessionId == null) {
throw new AssertionError("missing sessionId");
}

// sessionId has the form:
// token:<accessToken>:<player UUID>
String accessToken = sessionId.split(":")[1];

return UrlUtils.openConnection(url, proxy);
String uuid = null;
uuid = MojangApi.getUuid(user, proxy);
if (uuid == null) {
return new ByteArrayUrlConnection(("Couldn't find UUID of " + user).getBytes("utf-8"));
}

URL url = new URL(ApiServers.getSessionURL() + "/session/minecraft/join");
HttpURLConnection connection = (HttpURLConnection) UrlUtils.openConnection(url, proxy);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "application/json");
try (OutputStream os = connection.getOutputStream()) {
String payload = "{"
+ "\"accessToken\": \"" + accessToken + "\","
+ "\"selectedProfile\": \"" + uuid + "\","
+ "\"serverId\": \"" + serverId + "\""
+ "}";
os.write(payload.getBytes("utf-8"));
}
int responseCode = connection.getResponseCode();

if (responseCode == 204) {
return new ByteArrayUrlConnection("OK".getBytes("utf-8"));
} else {
return new ByteArrayUrlConnection("Bad login".getBytes("utf-8"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ static URLConnection openConnection(URL address, Proxy proxy) throws IOException
if (capeOwner != null) {
// since we do not need to process the image, open a direct connection bypassing
// Handler
Texture texture = MojangApi.getTexture(MojangApi.getUuid(capeOwner), "CAPE");
Texture texture = MojangApi.getTexture(MojangApi.getUuid(capeOwner, proxy), "CAPE");
if (texture == null)
return null;

Expand All @@ -91,7 +91,7 @@ static URLConnection openConnection(URL address, Proxy proxy) throws IOException
}

private static URLConnection getSkinConnection(String owner, Proxy proxy) throws IOException {
Texture texture = MojangApi.getTexture(MojangApi.getUuid(owner), "SKIN");
Texture texture = MojangApi.getTexture(MojangApi.getUuid(owner, proxy), "SKIN");
if (texture == null)
return null;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Fjord Launcher - Minecraft Launcher
* Copyright (C) 2024 Evan Goode <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package org.prismlauncher.legacy.utils.api;

public class ApiServers {
public static String getAuthURL() {
return getPropertyWithFallback("minecraft.api.auth.host", "https://authserver.mojang.com");
}
public static String getAccountURL() {
return getPropertyWithFallback("minecraft.api.account.host", "https://api.mojang.com");
}
public static String getSessionURL() {
return getPropertyWithFallback("minecraft.api.session.host", "https://sessionserver.mojang.com");
}
public static String getServicesURL() {
return getPropertyWithFallback("minecraft.api.services.host", "https://api.minecraftservices.com");
}
private static String getPropertyWithFallback(String key, String fallback) {
String value = System.getProperty(key);
if (value == null) {
return fallback;
}
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,38 @@
package org.prismlauncher.legacy.utils.api;

import org.prismlauncher.legacy.utils.Base64;
import org.prismlauncher.legacy.utils.api.ApiServers;
import org.prismlauncher.legacy.utils.json.JsonParser;
import org.prismlauncher.legacy.utils.url.UrlUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.util.List;
import java.util.Map;

/**
* Basic wrapper for Mojang's Minecraft API.
*/
@SuppressWarnings("unchecked")
public final class MojangApi {
public static String getUuid(String username) throws IOException {
try (InputStream in = new URL("https://api.mojang.com/users/profiles/minecraft/" + username).openStream()) {
Map<String, Object> map = (Map<String, Object>) JsonParser.parse(in);
return (String) map.get("id");
public static String getUuid(String username, Proxy proxy) throws IOException {
URL url = new URL(ApiServers.getAccountURL() + "/profiles/minecraft");
HttpURLConnection connection = (HttpURLConnection) UrlUtils.openConnection(url, proxy);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "application/json");
try (OutputStream os = connection.getOutputStream()) {
String payload = "[\"" + username + "\"]";
os.write(payload.getBytes("utf-8"));
}
try (InputStream in = connection.getInputStream()) {
List<Map<String, Object>> list = (List<Map<String, Object>>) JsonParser.parse(in);
return (String) list.get(0).get("id");
}
}

Expand Down Expand Up @@ -79,7 +95,7 @@ public static Texture getTexture(String player, String id) throws IOException {
}

public static Map<String, Object> getTextures(String player) throws IOException {
try (InputStream profileIn = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + player).openStream()) {
try (InputStream profileIn = new URL(ApiServers.getSessionURL() + "/session/minecraft/profile/" + player).openStream()) {
Map<String, Object> profile = (Map<String, Object>) JsonParser.parse(profileIn);

for (Map<String, Object> property : (Iterable<Map<String, Object>>) profile.get("properties")) {
Expand Down

0 comments on commit 9bc27cb

Please sign in to comment.