From ace755230ebce63abb8e23e7355a1f28c2e371f7 Mon Sep 17 00:00:00 2001
From: Gravita <12893402+gravit0@users.noreply.github.com>
Date: Sun, 24 Mar 2024 16:12:35 +0300
Subject: [PATCH] Use Launcher Auth

---
 proxy/pom.xml                                 | 12 +++
 .../bungee/connection/InitialHandler.java     | 56 ++++++-------
 .../net/md_5/bungee/util/LauncherUtil.java    | 78 +++++++++++++++++++
 3 files changed, 115 insertions(+), 31 deletions(-)
 create mode 100644 proxy/src/main/java/net/md_5/bungee/util/LauncherUtil.java

diff --git a/proxy/pom.xml b/proxy/pom.xml
index 15887222..5f91b017 100644
--- a/proxy/pom.xml
+++ b/proxy/pom.xml
@@ -106,6 +106,18 @@
             <version>5.0.4</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>pro.gravit.launcher</groupId>
+            <artifactId>launcher-core</artifactId>
+            <version>5.6.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>pro.gravit.launcher</groupId>
+            <artifactId>launcher-ws-api</artifactId>
+            <version>5.6.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
         <dependency>
             <groupId>com.mysql</groupId>
             <artifactId>mysql-connector-j</artifactId>
diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
index 0b5bee55..4ace5efe 100644
--- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
+++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
@@ -77,7 +77,11 @@ import net.md_5.bungee.protocol.packet.StatusRequest;
 import net.md_5.bungee.protocol.packet.StatusResponse;
 import net.md_5.bungee.util.AllowedCharacters;
 import net.md_5.bungee.util.BufUtil;
+import net.md_5.bungee.util.LauncherUtil;
 import net.md_5.bungee.util.QuietException;
+import pro.gravit.launcher.base.api.ConfigService;
+import pro.gravit.launcher.base.request.Request;
+import pro.gravit.launcher.base.request.auth.CheckServerRequest;
 
 @RequiredArgsConstructor
 public class InitialHandler extends PacketHandler implements PendingConnection
@@ -531,8 +535,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection
         BungeeCipher encrypt = EncryptionUtil.getCipher( true, sharedKey );
         ch.addBefore( PipelineUtils.FRAME_PREPENDER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) );
 
-        String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" );
-
         MessageDigest sha = MessageDigest.getInstance( "SHA-1" );
         for ( byte[] bit : new byte[][]
         {
@@ -541,37 +543,29 @@ public class InitialHandler extends PacketHandler implements PendingConnection
         {
             sha.update( bit );
         }
-        String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" );
-
-        String preventProxy = ( BungeeCord.getInstance().config.isPreventProxyConnections() && getSocketAddress() instanceof InetSocketAddress ) ? "&ip=" + URLEncoder.encode( getAddress().getAddress().getHostAddress(), "UTF-8" ) : "";
-        String authURL = String.format( MOJANG_AUTH_URL, encName, encodedHash, preventProxy );
-
-        Callback<String> handler = new Callback<String>()
-        {
-            @Override
-            public void done(String result, Throwable error)
+        String serverId = new BigInteger( sha.digest() ).toString( 16 );
+
+        Request.getRequestService().request(new CheckServerRequest(InitialHandler.this.getName(), serverId,
+                              ConfigService.checkServerConfig.needHardware,
+                              ConfigService.checkServerConfig.needProperties)).handleAsync((res, thr) -> {
+            if(thr != null) {
+                disconnect( bungee.getTranslation( "mojang_fail" ) );
+                bungee.getLogger().log( Level.SEVERE, "Error authenticating " + getName() + " with Launcher", thr );
+                return null;
+            }
+            LoginResult obj = LauncherUtil.makeLoginResult(res);
+            if (obj != null && obj.getId() != null )
             {
-                if ( error == null )
-                {
-                    LoginResult obj = BungeeCord.getInstance().gson.fromJson( result, LoginResult.class );
-                    if ( obj != null && obj.getId() != null )
-                    {
-                        loginProfile = obj;
-                        name = obj.getName();
-                        uniqueId = Util.getUUID( obj.getId() );
-                        finish();
-                        return;
-                    }
-                    disconnect( bungee.getTranslation( "offline_mode_player" ) );
-                } else
-                {
-                    disconnect( bungee.getTranslation( "mojang_fail" ) );
-                    bungee.getLogger().log( Level.SEVERE, "Error authenticating " + getName() + " with minecraft.net", error );
-                }
+                loginProfile = obj;
+                name = obj.getName();
+                uniqueId = Util.getUUID( obj.getId() );
+                finish();
+                return null;
             }
-        };
-        //thisState = State.FINISHING; // Waterfall - move earlier
-        HttpClient.get( authURL, ch.getHandle().eventLoop(), handler );
+            disconnect( bungee.getTranslation( "offline_mode_player" ) );
+            return null;
+        }, ch.getHandle().eventLoop());
+        thisState = State.FINISHING;
     }
 
     private void finish()
diff --git a/proxy/src/main/java/net/md_5/bungee/util/LauncherUtil.java b/proxy/src/main/java/net/md_5/bungee/util/LauncherUtil.java
new file mode 100644
index 00000000..c90b6058
--- /dev/null
+++ b/proxy/src/main/java/net/md_5/bungee/util/LauncherUtil.java
@@ -0,0 +1,78 @@
+
+package net.md_5.bungee.util;
+
+import net.md_5.bungee.connection.LoginResult;
+import net.md_5.bungee.protocol.Property;
+import pro.gravit.launcher.base.Launcher;
+import pro.gravit.launcher.base.events.request.CheckServerRequestEvent;
+import pro.gravit.launcher.base.profiles.PlayerProfile;
+import pro.gravit.launcher.base.profiles.Texture;
+import pro.gravit.utils.helper.SecurityHelper;
+
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+public class LauncherUtil {
+    private static final String SESSION_ID_PROPERTY = "launcher_session_id";
+    private static final String HARDWARE_ID_PROPERTY = "launcher_hardware_id";
+    private static final String CUSTOM_PROPERTY_PREFIX = "launcher_";
+    public static LoginResult makeLoginResult(CheckServerRequestEvent event) {
+        if(event == null || event.playerProfile == null) {
+            return null;
+        }
+        PlayerProfile profile = event.playerProfile;
+        List<Property> properties = new ArrayList<>();
+        for (Map.Entry<String, String> e : profile.properties.entrySet()) {
+            properties.add(new Property(e.getKey(), e.getValue(), ""));
+        }
+        if(event.sessionId != null) {
+            properties.add(new Property(SESSION_ID_PROPERTY, event.sessionId, ""));
+        }
+        if(event.hardwareId != null) {
+            properties.add(new Property(HARDWARE_ID_PROPERTY, event.hardwareId, ""));
+        }
+        if(event.sessionProperties != null) {
+            for (Map.Entry<String, String> e : event.sessionProperties.entrySet()) {
+                properties.add(new Property(CUSTOM_PROPERTY_PREFIX+e.getKey(), e.getValue(), ""));
+            }
+        }
+        {
+            String key = "textures";
+            GameProfileTextureProperties textureProperty = new GameProfileTextureProperties();
+            textureProperty.profileId = event.playerProfile.uuid.toString().replace("-", "");
+            textureProperty.profileName = event.playerProfile.username;
+            textureProperty.timestamp = System.currentTimeMillis();
+            for (Map.Entry<String, Texture> texture : profile.assets.entrySet()) {
+                textureProperty.textures.put(texture.getKey(), new GameProfileTextureProperties.GameTexture(texture.getValue()));
+            }
+            String value = Base64.getEncoder().encodeToString(Launcher.gsonManager.gson.toJson(textureProperty).getBytes(StandardCharsets.UTF_8));
+            properties.add(new Property(key, value, ""));
+        }
+        return new LoginResult(profile.uuid.toString().replace("-", ""), profile.username, properties.toArray(new Property[0]));
+    }
+
+    public static class GameProfileTextureProperties {
+        public long timestamp;
+        public String profileId;
+        public String profileName;
+        public Map<String, GameTexture> textures = new HashMap<>();
+
+        public static class GameTexture {
+            public String url;
+            public String hash;
+            public Map<String, String> metadata;
+
+            public GameTexture(String url, String hash, Map<String, String> metadata) {
+                this.url = url;
+                this.hash = hash;
+                this.metadata = metadata;
+            }
+
+            public GameTexture(Texture texture) {
+                this.url = texture.url;
+                this.hash = texture.digest == null ? null : SecurityHelper.toHex(texture.digest);
+                this.metadata = texture.metadata;
+            }
+        }
+    }
+}
-- 
2.44.0

