[ANY] Remove authlib

This commit is contained in:
Gravita 2022-02-11 16:12:24 +07:00
parent 5fb3a40bbc
commit fecf458e82
11 changed files with 2 additions and 592 deletions

View file

@ -1,8 +0,0 @@
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
dependencies {
api project(':LauncherAPI')
compileOnly group: 'com.google.guava', name: 'guava', version: rootProject['verGuavaC']
api files('../compat/authlib/authlib-clean.jar')
}

View file

@ -1,69 +0,0 @@
package com.mojang.authlib.minecraft;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
public class MinecraftProfileTexture {
public static final Set<Type> PROFILE_TEXTURE_TYPES = Collections.unmodifiableSet(EnumSet.allOf(Type.class));
public static final int PROFILE_TEXTURE_COUNT = PROFILE_TEXTURE_TYPES.size();
// Instance
private final String url;
private final String hash;
private final Map<String, String> metadata;
public MinecraftProfileTexture(String url) {
this(url, baseName(url));
}
public MinecraftProfileTexture(String url, String hash) {
this.url = url;
this.hash = hash;
this.metadata = null;
}
public MinecraftProfileTexture(String url, String hash, Map<String, String> metadata) {
this.url = url;
this.hash = hash;
this.metadata = metadata;
}
private static String baseName(String url) {
String name = url.substring(url.lastIndexOf('/') + 1);
// Remove index
int extensionIndex = name.lastIndexOf('.');
if (extensionIndex >= 0)
name = name.substring(0, extensionIndex);
// We're done
return name;
}
public String getHash() {
return hash;
}
public String getMetadata(String key) {
if (metadata == null) {
return null;
}
return metadata.get(key);
}
public String getUrl() {
return url;
}
@Override
public String toString() {
return String.format("MinecraftProfileTexture{url='%s',hash=%s}", url, hash);
}
public enum Type {
SKIN,
CAPE,
ELYTRA
}
}

View file

@ -1,52 +0,0 @@
package com.mojang.authlib.yggdrasil;
import pro.gravit.launcher.profiles.PlayerProfile;
import pro.gravit.launcher.request.auth.CheckServerRequest;
import pro.gravit.launcher.request.auth.JoinServerRequest;
import pro.gravit.launcher.request.uuid.BatchProfileByUsernameRequest;
import pro.gravit.launcher.request.uuid.ProfileByUUIDRequest;
import pro.gravit.launcher.request.uuid.ProfileByUsernameRequest;
import pro.gravit.utils.helper.LogHelper;
import java.util.UUID;
// Used to bypass Launcher's class name obfuscation and access API
public class CompatBridge {
public static final int PROFILES_MAX_BATCH_SIZE = 128;
private CompatBridge() {
}
public static CompatProfile checkServer(String username, String serverID) throws Exception {
LogHelper.debug("CompatBridge.checkServer, Username: '%s', Server ID: %s", username, serverID);
return CompatProfile.fromPlayerProfile(new CheckServerRequest(username, serverID).request().playerProfile);
}
public static boolean joinServer(String username, String accessToken, String serverID) throws Exception {
// Join server
LogHelper.debug("LegacyBridge.joinServer, Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID);
return new JoinServerRequest(username, accessToken, serverID).request().allow;
}
public static CompatProfile profileByUsername(String username) throws Exception {
return CompatProfile.fromPlayerProfile(new ProfileByUsernameRequest(username).request().playerProfile);
}
public static CompatProfile profileByUUID(UUID uuid) throws Exception {
return CompatProfile.fromPlayerProfile(new ProfileByUUIDRequest(uuid).request().playerProfile);
}
public static CompatProfile[] profilesByUsername(String... usernames) throws Exception {
PlayerProfile[] profiles = new BatchProfileByUsernameRequest(usernames).request().playerProfiles;
// Convert profiles
CompatProfile[] resultProfiles = new CompatProfile[profiles.length];
for (int i = 0; i < profiles.length; i++)
resultProfiles[i] = CompatProfile.fromPlayerProfile(profiles[i]);
// We're dones
return resultProfiles;
}
}

View file

@ -1,52 +0,0 @@
package com.mojang.authlib.yggdrasil;
import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.profiles.PlayerProfile;
import pro.gravit.utils.helper.SecurityHelper;
import java.util.UUID;
public class CompatProfile {
public static final String SKIN_URL_PROPERTY = Launcher.SKIN_URL_PROPERTY;
public static final String SKIN_DIGEST_PROPERTY = Launcher.SKIN_DIGEST_PROPERTY;
public static final String CLOAK_URL_PROPERTY = Launcher.CLOAK_URL_PROPERTY;
public static final String CLOAK_DIGEST_PROPERTY = Launcher.CLOAK_DIGEST_PROPERTY;
// Instance
public final UUID uuid;
public final String uuidHash, username;
public final String skinURL, skinDigest;
public final String cloakURL, cloakDigest;
public CompatProfile(UUID uuid, String username, String skinURL, String skinDigest, String cloakURL, String cloakDigest) {
this.uuid = uuid;
uuidHash = Launcher.toHash(uuid);
this.username = username;
this.skinURL = skinURL;
this.skinDigest = skinDigest;
this.cloakURL = cloakURL;
this.cloakDigest = cloakDigest;
}
public static CompatProfile fromPlayerProfile(PlayerProfile profile) {
return profile == null ? null : new CompatProfile(profile.uuid, profile.username,
profile.skin == null ? null : profile.skin.url,
profile.skin == null ? null : SecurityHelper.toHex(profile.skin.digest),
profile.cloak == null ? null : profile.cloak.url,
profile.cloak == null ? null : SecurityHelper.toHex(profile.cloak.digest)
);
}
public int countProperties() {
int count = 0;
if (skinURL != null)
count++;
if (skinDigest != null)
count++;
if (cloakURL != null)
count++;
if (cloakDigest != null)
count++;
return count;
}
}

View file

@ -1,42 +0,0 @@
package com.mojang.authlib.yggdrasil;
import pro.gravit.launcher.request.auth.CheckServerRequest;
import pro.gravit.launcher.request.auth.JoinServerRequest;
import pro.gravit.utils.helper.CommonHelper;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.LogHelper;
// Used by 1.6.4 and below versions
public class LegacyBridge {
private LegacyBridge() {
}
public static boolean checkServer(String username, String serverID) throws Exception {
LogHelper.debug("LegacyBridge.checkServer, Username: '%s', Server ID: %s", username, serverID);
return new CheckServerRequest(username, serverID).request() != null;
}
public static String getCloakURL(String username) {
LogHelper.debug("LegacyBridge.getCloakURL: '%s'", username);
return CommonHelper.replace(System.getProperty("launcher.legacy.cloaksURL",
"http://skins.minecraft.net/MinecraftCloaks/%username%.png"), "username", IOHelper.urlEncode(username));
}
public static String getSkinURL(String username) {
LogHelper.debug("LegacyBridge.getSkinURL: '%s'", username);
return CommonHelper.replace(System.getProperty("launcher.legacy.skinsURL",
"http://skins.minecraft.net/MinecraftSkins/%username%.png"), "username", IOHelper.urlEncode(username));
}
public static String joinServer(String username, String accessToken, String serverID) {
// Join server
LogHelper.debug("LegacyBridge.joinServer, Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID);
try {
return new JoinServerRequest(username, accessToken, serverID).request().allow ? "OK" : "Bad Login (Clientside)";
} catch (Exception e) {
return e.toString();
}
}
}

View file

@ -1,31 +0,0 @@
package com.mojang.authlib.yggdrasil;
import com.mojang.authlib.Agent;
import com.mojang.authlib.AuthenticationService;
import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.UserAuthentication;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import pro.gravit.utils.helper.LogHelper;
import java.net.Proxy;
public class YggdrasilAuthenticationService implements AuthenticationService {
public YggdrasilAuthenticationService(Proxy proxy, String clientToken) {
LogHelper.debug("Patched AuthenticationService created: '%s'", clientToken);
}
@Override
public MinecraftSessionService createMinecraftSessionService() {
return new YggdrasilMinecraftSessionService(this);
}
@Override
public GameProfileRepository createProfileRepository() {
return new YggdrasilGameProfileRepository();
}
@Override
public UserAuthentication createUserAuthentication(Agent agent) {
throw new UnsupportedOperationException("createUserAuthentication is used only by Mojang Launcher");
}
}

View file

@ -1,85 +0,0 @@
package com.mojang.authlib.yggdrasil;
import com.mojang.authlib.Agent;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.ProfileLookupCallback;
import pro.gravit.launcher.profiles.PlayerProfile;
import pro.gravit.launcher.request.uuid.BatchProfileByUsernameRequest;
import pro.gravit.utils.helper.LogHelper;
import pro.gravit.utils.helper.VerifyHelper;
import java.util.Arrays;
import java.util.UUID;
public class YggdrasilGameProfileRepository implements GameProfileRepository {
private static final long BUSY_WAIT_MS = VerifyHelper.verifyLong(
Long.parseLong(System.getProperty("launcher.com.mojang.authlib.busyWait", Long.toString(100L))),
VerifyHelper.L_NOT_NEGATIVE, "launcher.com.mojang.authlib.busyWait can't be < 0");
private static final long ERROR_BUSY_WAIT_MS = VerifyHelper.verifyLong(
Long.parseLong(System.getProperty("launcher.com.mojang.authlib.errorBusyWait", Long.toString(500L))),
VerifyHelper.L_NOT_NEGATIVE, "launcher.com.mojang.authlib.errorBusyWait can't be < 0");
public YggdrasilGameProfileRepository() {
LogHelper.debug("Patched GameProfileRepository created");
}
private static void busyWait(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
LogHelper.error(e);
}
}
@Override
public void findProfilesByNames(String[] usernames, Agent agent, ProfileLookupCallback callback) {
int offset = 0;
while (offset < usernames.length) {
String[] sliceUsernames = Arrays.copyOfRange(usernames, offset, Math.min(offset + 128, usernames.length));
offset += 128;
// Batch Username-To-UUID request
PlayerProfile[] sliceProfiles;
try {
sliceProfiles = new BatchProfileByUsernameRequest(sliceUsernames).request().playerProfiles;
} catch (Exception e) {
boolean debug = LogHelper.isDebugEnabled();
for (String username : sliceUsernames) {
if (debug) {
LogHelper.debug("Couldn't find profile '%s': %s", username, e);
}
callback.onProfileLookupFailed(new GameProfile((UUID) null, username), e);
}
// Busy wait, like in standard com.mojang.authlib
busyWait(ERROR_BUSY_WAIT_MS);
continue;
}
// Request succeeded!
int len = sliceProfiles.length;
boolean debug = len > 0 && LogHelper.isDebugEnabled();
for (int i = 0; i < len; i++) {
PlayerProfile pp = sliceProfiles[i];
if (pp == null) {
String username = sliceUsernames[i];
if (debug) {
LogHelper.debug("Couldn't find profile '%s'", username);
}
callback.onProfileLookupFailed(new GameProfile((UUID) null, username), new ProfileNotFoundException("Server did not find the requested profile"));
continue;
}
// Report as looked up
if (debug) {
LogHelper.debug("Successfully looked up profile '%s'", pp.username);
}
callback.onProfileLookupSucceeded(YggdrasilMinecraftSessionService.toGameProfile(pp));
}
// Busy wait, like in standard com.mojang.authlib
busyWait(BUSY_WAIT_MS);
}
}
}

View file

@ -1,250 +0,0 @@
package com.mojang.authlib.yggdrasil;
import com.google.common.collect.Iterables;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import com.mojang.authlib.AuthenticationService;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.exceptions.AuthenticationUnavailableException;
import com.mojang.authlib.minecraft.BaseMinecraftSessionService;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.profiles.PlayerProfile;
import pro.gravit.launcher.request.auth.CheckServerRequest;
import pro.gravit.launcher.request.auth.JoinServerRequest;
import pro.gravit.launcher.request.uuid.ProfileByUUIDRequest;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.LogHelper;
import pro.gravit.utils.helper.SecurityHelper;
import java.lang.reflect.Type;
import java.net.InetAddress;
import java.util.Base64;
import java.util.EnumMap;
import java.util.Map;
import java.util.UUID;
public class YggdrasilMinecraftSessionService extends BaseMinecraftSessionService {
public static final boolean NO_TEXTURES = Boolean.getBoolean("launcher.com.mojang.authlib.noTextures");
private static final Gson gson = new Gson();
public YggdrasilMinecraftSessionService(AuthenticationService service) {
super(service);
LogHelper.debug("Patched MinecraftSessionService created");
}
public YggdrasilMinecraftSessionService(YggdrasilAuthenticationService service) {
super(service);
LogHelper.debug("Patched MinecraftSessionService created");
}
public static void fillTextureProperties(GameProfile profile, PlayerProfile pp) {
boolean debug = LogHelper.isDebugEnabled();
if (debug) {
LogHelper.debug("fillTextureProperties, Username: '%s'", profile.getName());
}
if (NO_TEXTURES)
return;
// Fill textures map
PropertyMap properties = profile.getProperties();
if (pp.skin != null) {
properties.put(Launcher.SKIN_URL_PROPERTY, new Property(Launcher.SKIN_URL_PROPERTY, pp.skin.url, ""));
properties.put(Launcher.SKIN_DIGEST_PROPERTY, new Property(Launcher.SKIN_DIGEST_PROPERTY, SecurityHelper.toHex(pp.skin.digest), ""));
if (pp.skin.metadata != null) {
String metadata = serializeMetadataMap(pp.skin.metadata);
properties.put(Launcher.SKIN_METADATA_PROPERTY, new Property(Launcher.SKIN_METADATA_PROPERTY, metadata, ""));
}
if (debug) {
LogHelper.debug("fillTextureProperties, Has skin texture for username '%s'", profile.getName());
}
}
if (pp.cloak != null) {
properties.put(Launcher.CLOAK_URL_PROPERTY, new Property(Launcher.CLOAK_URL_PROPERTY, pp.cloak.url, ""));
properties.put(Launcher.CLOAK_DIGEST_PROPERTY, new Property(Launcher.CLOAK_DIGEST_PROPERTY, SecurityHelper.toHex(pp.cloak.digest), ""));
if (pp.cloak.metadata != null) {
String metadata = serializeMetadataMap(pp.cloak.metadata);
properties.put(Launcher.CLOAK_METADATA_PROPERTY, new Property(Launcher.SKIN_METADATA_PROPERTY, metadata, ""));
}
if (debug) {
LogHelper.debug("fillTextureProperties, Has cloak texture for username '%s'", profile.getName());
}
}
}
private static String serializeMetadataMap(Map<String, String> map) {
if (map == null) {
return null;
}
return gson.toJson(map);
}
private static Map<String, String> deserializeMetadataMap(String value) {
Type typeOfMap = new TypeToken<Map<String, String>>() {
}.getType();
return gson.fromJson(value, typeOfMap);
}
private static void getTexturesMojang(Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures, String texturesBase64, GameProfile profile) {
// Decode textures payload
JsonObject texturesJSON;
try {
byte[] decoded = Base64.getDecoder().decode(texturesBase64);
texturesJSON = JsonParser.parseString(new String(decoded, IOHelper.UNICODE_CHARSET)).getAsJsonObject().getAsJsonObject("textures");
} catch (Exception ignored) {
LogHelper.error("Could not decode textures payload, Username: '%s', UUID: '%s'", profile.getName(), profile.getUUID());
return;
}
// Fetch textures from textures JSON
for (MinecraftProfileTexture.Type type : MinecraftProfileTexture.PROFILE_TEXTURE_TYPES) {
if (textures.containsKey(type))
continue; // Overriden by launcher
// Get texture from JSON
JsonElement textureJSON = texturesJSON.get(type.name());
if (textureJSON != null && textureJSON.isJsonObject()) {
JsonElement urlValue = textureJSON.getAsJsonObject().get("url");
if (urlValue.isJsonPrimitive())
textures.put(type, new MinecraftProfileTexture(urlValue.getAsString()));
}
}
}
public static GameProfile toGameProfile(PlayerProfile pp) {
GameProfile profile = new GameProfile(pp.uuid, pp.username);
fillTextureProperties(profile, pp);
return profile;
}
@Override
public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) {
// Verify has UUID
UUID uuid = profile.getUUID();
boolean debug = LogHelper.isDebugEnabled();
if (debug) {
LogHelper.debug("fillProfileProperties, UUID: %s", uuid);
}
if (uuid == null)
return profile;
// Make profile request
PlayerProfile pp;
try {
pp = new ProfileByUUIDRequest(uuid).request().playerProfile;
} catch (Exception e) {
if (debug) {
LogHelper.debug("Couldn't fetch profile properties for '%s': %s", profile, e);
}
return profile;
}
// Verify is found
if (pp == null) {
if (debug) {
LogHelper.debug("Couldn't fetch profile properties for '%s' as the profile does not exist", profile);
}
return profile;
}
// Create new game profile from player profile
if (debug) {
LogHelper.debug("Successfully fetched profile properties for '%s'", profile);
}
fillTextureProperties(profile, pp);
return toGameProfile(pp);
}
@Override
public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getTextures(GameProfile profile, boolean requireSecure) {
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("getTextures, Username: '%s', UUID: '%s'", profile.getName(), profile.getUUID());
}
Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures = new EnumMap<>(MinecraftProfileTexture.Type.class);
// Add textures
if (!NO_TEXTURES) {
// Add skin URL to textures map
Property skinURL = Iterables.getFirst(profile.getProperties().get(Launcher.SKIN_URL_PROPERTY), null);
Property skinDigest = Iterables.getFirst(profile.getProperties().get(Launcher.SKIN_DIGEST_PROPERTY), null);
Property skinMetadata = Iterables.getFirst(profile.getProperties().get(Launcher.SKIN_METADATA_PROPERTY), null);
if (skinURL != null && skinDigest != null)
textures.put(MinecraftProfileTexture.Type.SKIN, new MinecraftProfileTexture(skinURL.getValue(), skinDigest.getValue(), skinMetadata == null ? null : deserializeMetadataMap(skinMetadata.getValue())));
// Add cloak URL to textures map
Property cloakURL = Iterables.getFirst(profile.getProperties().get(Launcher.CLOAK_URL_PROPERTY), null);
Property cloakDigest = Iterables.getFirst(profile.getProperties().get(Launcher.CLOAK_DIGEST_PROPERTY), null);
Property cloakMetadata = Iterables.getFirst(profile.getProperties().get(Launcher.CLOAK_METADATA_PROPERTY), null);
if (cloakURL != null && cloakDigest != null)
textures.put(MinecraftProfileTexture.Type.CAPE, new MinecraftProfileTexture(cloakURL.getValue(), cloakDigest.getValue(), cloakMetadata == null ? null : deserializeMetadataMap(cloakMetadata.getValue())));
// Try to find missing textures in textures payload (now always true because launcher is not passing elytra skins)
if (textures.size() != MinecraftProfileTexture.PROFILE_TEXTURE_COUNT) {
Property texturesMojang = Iterables.getFirst(profile.getProperties().get("textures"), null);
if (texturesMojang != null)
getTexturesMojang(textures, texturesMojang.getValue(), profile);
}
}
// Return filled textures
return textures;
}
@Override
public GameProfile hasJoinedServer(GameProfile profile, String serverID) throws AuthenticationUnavailableException {
String username = profile.getName();
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("checkServer, Username: '%s', Server ID: %s", username, serverID);
}
// Make checkServer request
PlayerProfile pp;
try {
pp = new CheckServerRequest(username, serverID).request().playerProfile;
} catch (Exception e) {
LogHelper.error(e);
throw new AuthenticationUnavailableException(e);
}
// Return profile if found
return pp == null ? null : toGameProfile(pp);
}
@Override
public GameProfile hasJoinedServer(GameProfile profile, String serverID, InetAddress address) throws AuthenticationUnavailableException {
return hasJoinedServer(profile, serverID);
}
public YggdrasilAuthenticationService getAuthenticationService() {
return (YggdrasilAuthenticationService) super.getAuthenticationService();
}
@Override
public void joinServer(GameProfile profile, String accessToken, String serverID) throws AuthenticationException {
// Join server
String username = profile.getName();
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("joinServer, Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID);
}
// Make joinServer request
boolean success;
try {
success = new JoinServerRequest(username, accessToken, serverID).request().allow;
} catch (Exception e) {
LogHelper.error(e);
throw new AuthenticationUnavailableException(e);
}
// Verify is success
if (!success)
throw new AuthenticationException("Bad Login (Clientside)");
}
}

View file

@ -37,7 +37,7 @@ task javadocJar(type: Jar) {
} }
dependencies { dependencies {
pack project(':LauncherAuthlib') pack project(':LauncherAPI')
pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty'] pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty']
} }

@ -1 +1 @@
Subproject commit 4eb5b32678202efcff2d7cf8f87bdf32eab5384d Subproject commit a8f7dd38a4a5cfabc4d5584afa22be8d566b7c61

View file

@ -3,7 +3,6 @@
include 'Launcher' include 'Launcher'
include 'LauncherCore' include 'LauncherCore'
include 'LauncherAPI' include 'LauncherAPI'
include 'LauncherAuthlib'
include 'ServerWrapper' include 'ServerWrapper'
include 'LaunchServer' include 'LaunchServer'
include 'modules' include 'modules'