Solved Bungeecord Login Protocol / Premium Username Login

Discussion in 'BungeeCord Plugin Development' started by MultiBallMC, Feb 20, 2021.

  1. Hey there!

    First of all, I am Spanish so sorry for my bad English.

    I am trying to create an auto-premium plugin and I was wondering how to do it. After some research on this forum, I find a lot of examples to use, but all of them are not up-to-dated so I cannot use them.

    I have been trying a lot of codes, like sending encryption packets to bungee connections
    Code (Java):
          e.getConnection().unsafe().sendPacket(EncryptionUtil.encryptRequest());
     
    but it always finishes throwing an error.

    So, anyone can explain me how to do it? I think that premium launchers sends "EncryptionResponse" packet so is there any way to handle that packet and do something with the premium connection? Like pushing it into a HashSet or something

    Add: I am using latest version of bungeecord
     
  2. Well, that classes maybe can help me. I found 2 interesting codes:
    Code (Java):
    @EventHandler
        public void onPreLogin(PreLoginEvent preLoginEvent) {
            if (preLoginEvent.isCancelled() || isBedrockPlayer(preLoginEvent.getConnection().getUniqueId())) {
                return;
            }

            PendingConnection connection = preLoginEvent.getConnection();
            if (!rateLimiter.tryAcquire()) {
                plugin.getLog().warn("Join limit hit - Ignoring player {}", connection);
                return;
            }

            InitialHandler initialHandler = (InitialHandler) connection;
            String username = initialHandler.getLoginRequest().getData();
            plugin.getLog().info("Incoming login request for {} from {}", username, initialHandler.getAddress());

            preLoginEvent.registerIntent(plugin);
            Runnable asyncPremiumCheck = new AsyncPremiumCheck(plugin, preLoginEvent, connection);
            plugin.getScheduler().runAsync(asyncPremiumCheck);
        }
    Code (Java):
    @Override
        public void run() {
            plugin.getSession().remove(connection);

            InitialHandler initialHandler = (InitialHandler) connection;
            String username = initialHandler.getLoginRequest().getData();
            try {
                super.onLogin(username, new BungeeLoginSource(connection, preLoginEvent));
            } finally {
                preLoginEvent.completeIntent(plugin);
            }
        }
    I will try to do something similar and I will edit this message

    Edit: Cannot do nothing, FastLogin uses a lot of custom classes to do it and I am probably not able to recreate those classes.

    Edit 2: Isn't there anyway to send EncryptRequest packet and await EncrypResponde is there? If there is EncryptResponse the player will be premium if not it will be no-premium
     
    #3 MultiBallMC, Feb 20, 2021
    Last edited: Feb 20, 2021
  3. You can use the Mojang API to check if is a premium account (in the
    PreLoginEvent, that is an Async event): https://api.mojang.com/users/profiles/minecraft/Username
    The output will be like this (if the username is premium):
    Else, the output will be empty.
    If returned true from API, you can call PendingConnection#setOnlineMode(true), and BungeeCord will do the rest.

    I advise you to keep the result stored in a database, because the API has a limit of 600 requests per 10 minutes.

    Remember to set onlineMode to false in server and bungeecord configuration, and also watch out for UUID changes that occur when the connection mode is changed.

    Sorry for bad english, i'm from Brazil.
     
  4. Well, sorry for been inactive... @Arkasher
    First, "https://api.mojang.com/users/profiles/minecraft/Username" only checks the username, in other words, if a cracked user uses a premium Username it will return the premium Uuid.
    Then, if I set player's online mode to true, players with cracked launcher will not be able to join. If this happens I can store 'em in a map if they are kicked and if they re-join the server to log like a normal cracked user.

    But is there a way to change the "Invalid session" message to something like "Relog to enter the server"
     
  5. Like i said, when you use PendingConnection#setOnlineMode(true), the Bungeecord will handle the connection with mojang, and allow the join only if the user is really a premium account and launcher. The online mode will be set just to the specified player. The Mojang API will be used to check if the username is premium or not.
     
  6. Yeah, but if the player is using a premium username without being premium, when I set the connection to premium it will be kicked
     
  7. And you will use the Mojang API to avoid this... If the API return is empty, you will not set player as premium.
     
  8. And the online mode should be set to false in server.properties and bungeecord configuration.
     
  9. But the mojang API is not 100% secure, I mean, if a cracked user enters with "TecnoBlade" name but it is not logged in minecraft because it is not premium, it will bypass mojang API (https://api.mojang.com/users/profiles/minecraft/TecnoBlade) but it won't bypass PendingConnection#.setOnlineMode(true)
     
  10. I think you don't understand. The API is just to verify if is a registered username. Who will check if the player are logged is the Bungeecord when you set the connection mode to true.
     
  11. Yes... but if I ser connection mode to true cracked players won't be able to enter, look, I am thinking the code like this:

    Code (Java):
    if(isRegisteredInMojang) {
      pendingConn.setOnlineMode(true)
      //If it is kicked Cracked, if not Premium
      return;
    }
    //Cracked
     
  12. But you want that same who has not premium account and join with premium nick be able to join?
     
  13. No, I don't want a cracked username enter like a premium account, that's the problen¡m
     
  14. Code (Text):
    //Set online-mode to false in server.properties and bungeecord config
    if(isRegisteredInMojang) {
      pendingConn.setOnlineMode(true);
      //It will just set onlineMode if user is registered. If is a non-registered username, it will not be kicked.
      return;
    }
    //Cracked
     
  15. Wait, we are going to satrt again because we are starting to mismanage this. When you are using an "unofficial" launcher you can use every kinda names, even it is premium or cracked. So, if a cracked username enters with a premium username "if(isRegisteredInMojang) {" this will be true because THAT name is registered in mojang like a premium name, but when I set the " pendingConn.setOnlineMode(true);" to true, the cracked username will be kicked because altought the username is registered like premium, the setOnlineMode uses "packets" for doing that, and the package it needs (EncryptationResponse) won't be received because the launcher it is using is not premium, and that packet only is sent by premium launchers.
     
  16. Test this:
    Code (Text):
    package test.Test;

    import net.md_5.bungee.api.event.PreLoginEvent;
    import net.md_5.bungee.api.plugin.Listener;
    import net.md_5.bungee.event.EventHandler;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;

    public class Test implements Listener {

        private HttpURLConnection getConnection(String url) throws IOException {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setConnectTimeout(1000);
            connection.setReadTimeout(1000);

            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("User-Agent", "Premium-Checker");

            return connection;
        }

        public boolean isPremiumUsername(String username) {
            boolean isPremiumUsername = false;

            try {
                HttpURLConnection conn = getConnection(
                        "https://api.mojang.com/users/profiles/minecraft/" + username);
                if (conn.getResponseCode() == 200) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    String line = reader.readLine();
                    isPremiumUsername = (line != null) && (!line.equals("null"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return isPremiumUsername;
        }

        @EventHandler
        public void onPreLoginEvent(PreLoginEvent event) {
            //PS: Set online-mode to false in server.properties and bungeecord config
            event.getConnection().setOnlineMode(isPremiumUsername(event.getConnection().getName()));
        }
    }
     
     
  17. I understand your point, but when you call setOnlineMode(true), the Bungeecord communicates with Mojang to check if the username is authenticated.
     
  18. Wait, what? You are right, I didn't take into account that the cracked user with premium username it ISN'T using an "official" launcher, so it'll be kicked, that why because I couldn't do it and understand, taking into apart that I am Spanish so I don't understand English well.


    Yeah

    So, thank you so much and sorry for misunderstanding your explanations :((

    Problem marked as solved <3