Launcher/LauncherAuthlib/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java

216 lines
9.3 KiB
Java
Raw Normal View History

2018-09-17 10:07:32 +03:00
package com.mojang.authlib.yggdrasil;
2019-06-03 10:58:10 +03:00
import java.net.InetAddress;
import java.util.Base64;
import java.util.EnumMap;
import java.util.Map;
import java.util.UUID;
2018-09-17 10:07:32 +03:00
import com.google.common.collect.Iterables;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
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;
2018-09-17 10:07:32 +03:00
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
2019-06-03 10:58:10 +03:00
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;
2018-09-17 10:07:32 +03:00
public final class YggdrasilMinecraftSessionService extends BaseMinecraftSessionService {
public static final JsonParser JSON_PARSER = new JsonParser();
2018-09-25 17:06:13 +03:00
public static final boolean NO_TEXTURES = Boolean.parseBoolean("launcher.com.mojang.authlib.noTextures");
2018-09-17 10:07:32 +03:00
public static void fillTextureProperties(GameProfile profile, PlayerProfile pp) {
2019-08-13 21:02:33 +03:00
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("fillTextureProperties, Username: '%s'", profile.getName());
}
2018-09-17 10:07:32 +03:00
if (NO_TEXTURES)
2018-09-22 17:33:00 +03:00
return;
2018-09-17 10:07:32 +03:00
// Fill textures map
PropertyMap properties = profile.getProperties();
if (pp.skin != null) {
2018-09-25 17:06:13 +03:00
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), ""));
2019-08-13 21:02:33 +03:00
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("fillTextureProperties, Has skin texture for username '%s'", profile.getName());
}
2018-09-17 10:07:32 +03:00
}
if (pp.cloak != null) {
2018-09-25 17:06:13 +03:00
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), ""));
2019-08-13 21:02:33 +03:00
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("fillTextureProperties, Has cloak texture for username '%s'", profile.getName());
}
2018-09-17 10:07:32 +03:00
}
}
2018-09-25 17:06:13 +03:00
private static void getTexturesMojang(Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures, String texturesBase64, GameProfile profile) {
2018-09-17 10:07:32 +03:00
// Decode textures payload
JsonObject texturesJSON;
try {
byte[] decoded = Base64.getDecoder().decode(texturesBase64);
texturesJSON = JSON_PARSER.parse(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
2018-09-25 17:06:13 +03:00
for (MinecraftProfileTexture.Type type : MinecraftProfileTexture.PROFILE_TEXTURE_TYPES) {
2018-09-17 10:07:32 +03:00
if (textures.containsKey(type))
2018-09-22 17:33:00 +03:00
continue; // Overriden by launcher
2018-09-17 10:07:32 +03:00
// Get texture from JSON
JsonElement textureJSON = texturesJSON.get(type.name());
if (textureJSON != null && textureJSON.isJsonObject()) {
JsonElement urlValue = textureJSON.getAsJsonObject().get("url");
if (urlValue.isJsonPrimitive())
2018-09-22 17:33:00 +03:00
textures.put(type, new MinecraftProfileTexture(urlValue.getAsString()));
2018-09-17 10:07:32 +03:00
}
}
}
public static GameProfile toGameProfile(PlayerProfile pp) {
GameProfile profile = new GameProfile(pp.uuid, pp.username);
fillTextureProperties(profile, pp);
return profile;
}
public YggdrasilMinecraftSessionService(AuthenticationService service) {
super(service);
LogHelper.debug("Patched MinecraftSessionService created");
}
@Override
public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) {
// Verify has UUID
UUID uuid = profile.getUUID();
2019-08-13 21:02:33 +03:00
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("fillProfileProperties, UUID: %s", uuid);
}
2018-09-17 10:07:32 +03:00
if (uuid == null)
2018-09-22 17:33:00 +03:00
return profile;
2018-09-17 10:07:32 +03:00
// Make profile request
PlayerProfile pp;
try {
2019-02-10 11:38:48 +03:00
pp = new ProfileByUUIDRequest(uuid).request().playerProfile;
2018-09-17 10:07:32 +03:00
} catch (Exception e) {
2019-08-13 21:02:33 +03:00
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("Couldn't fetch profile properties for '%s': %s", profile, e);
}
2018-09-17 10:07:32 +03:00
return profile;
}
// Verify is found
if (pp == null) {
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
2019-08-13 21:02:33 +03:00
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("Successfully fetched profile properties for '%s'", profile);
}
2018-09-17 10:07:32 +03:00
fillTextureProperties(profile, pp);
return toGameProfile(pp);
}
@Override
2018-09-25 17:06:13 +03:00
public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getTextures(GameProfile profile, boolean requireSecure) {
2019-08-13 21:02:33 +03:00
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("getTextures, Username: '%s', UUID: '%s'", profile.getName(), profile.getUUID());
}
2018-09-25 17:06:13 +03:00
Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures = new EnumMap<>(MinecraftProfileTexture.Type.class);
2018-09-17 10:07:32 +03:00
// Add textures
if (!NO_TEXTURES) {
// Add skin URL to textures map
2018-09-25 17:06:13 +03:00
Property skinURL = Iterables.getFirst(profile.getProperties().get(Launcher.SKIN_URL_PROPERTY), null);
Property skinDigest = Iterables.getFirst(profile.getProperties().get(Launcher.SKIN_DIGEST_PROPERTY), null);
2018-09-17 10:07:32 +03:00
if (skinURL != null && skinDigest != null)
2018-09-25 17:06:13 +03:00
textures.put(MinecraftProfileTexture.Type.SKIN, new MinecraftProfileTexture(skinURL.getValue(), skinDigest.getValue()));
2018-09-17 10:07:32 +03:00
// Add cloak URL to textures map
2018-09-25 17:06:13 +03:00
Property cloakURL = Iterables.getFirst(profile.getProperties().get(Launcher.CLOAK_URL_PROPERTY), null);
Property cloakDigest = Iterables.getFirst(profile.getProperties().get(Launcher.CLOAK_DIGEST_PROPERTY), null);
2018-09-17 10:07:32 +03:00
if (cloakURL != null && cloakDigest != null)
2018-09-25 17:06:13 +03:00
textures.put(MinecraftProfileTexture.Type.CAPE, new MinecraftProfileTexture(cloakURL.getValue(), cloakDigest.getValue()));
2018-09-17 10:07:32 +03:00
// 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)
2018-09-22 17:33:00 +03:00
getTexturesMojang(textures, texturesMojang.getValue(), profile);
2018-09-17 10:07:32 +03:00
}
}
// Return filled textures
return textures;
}
@Override
public GameProfile hasJoinedServer(GameProfile profile, String serverID) throws AuthenticationUnavailableException {
String username = profile.getName();
2019-08-13 21:02:33 +03:00
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("checkServer, Username: '%s', Server ID: %s", username, serverID);
}
2018-09-17 10:07:32 +03:00
// Make checkServer request
PlayerProfile pp;
try {
2019-02-10 11:38:48 +03:00
pp = new CheckServerRequest(username, serverID).request().playerProfile;
2018-09-17 10:07:32 +03:00
} 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);
}
2018-09-22 17:33:00 +03:00
2018-09-19 15:03:52 +03:00
public YggdrasilAuthenticationService getAuthenticationService() {
2018-09-22 17:33:00 +03:00
return (YggdrasilAuthenticationService) super.getAuthenticationService();
2018-09-19 15:03:52 +03:00
}
2018-09-22 17:33:00 +03:00
2018-09-17 10:07:32 +03:00
@Override
public void joinServer(GameProfile profile, String accessToken, String serverID) throws AuthenticationException {
// Join server
String username = profile.getName();
2019-08-13 21:02:33 +03:00
if (LogHelper.isDebugEnabled()) {
LogHelper.debug("joinServer, Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID);
}
2018-09-17 10:07:32 +03:00
// Make joinServer request
boolean success;
try {
2019-02-10 11:38:48 +03:00
success = new JoinServerRequest(username, accessToken, serverID).request().allow;
2018-09-17 10:07:32 +03:00
} catch (Exception e) {
throw new AuthenticationUnavailableException(e);
}
// Verify is success
if (!success)
2018-09-22 17:33:00 +03:00
throw new AuthenticationException("Bad Login (Clientside)");
2018-09-17 10:07:32 +03:00
}
}