Newer
Older
KeeperJerry_Launcher / LaunchServer / source / auth / provider / MineSocialAuthProvider.java
package launchserver.auth.provider;

import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import launcher.serialize.config.entry.BlockConfigEntry;
import launchserver.helpers.HTTPRequestHelper;

import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import java.util.regex.Pattern;

public class MineSocialAuthProvider extends AuthProvider
{
    private static final Pattern UUID_REGEX = Pattern.compile("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})");
    private static final java.net.URL URL;

    static
    {
        try
        {
            URL = new URL("https://authserver.minesocial.net/authenticate");
        }
        catch (MalformedURLException e)
        {
            throw new InternalError(e);
        }
    }

    MineSocialAuthProvider(BlockConfigEntry block)
    {
        super(block);
    }

    @Override
    public AuthProviderResult auth(String login, String password, String ip) throws Throwable
    {
        String clientToken = UUID.randomUUID().toString().replaceAll("-", "");
        // https://wiki.vg/Authentication#Payload
        JsonObject request = Json.object().
                add("agent", Json.object().add("name", "Minecraft").add("version", 1)).
                add("username", login).add("password", getHash(password)).add("clientToken", clientToken).
                add("crypto", "SHA-1");

        // Verify there's no error
        JsonObject response = HTTPRequestHelper.makeAuthlibRequest(URL, request, "MineSocial");
        if (response == null)
        {
            authError("Empty MineSocial Provider response");
        }
        JsonValue errorMessage = response.get("errorMessage");
        if (errorMessage != null)
        {
            authError(errorMessage.asString());
        }

        // Parse JSON data
        JsonObject selectedProfile = response.get("selectedProfile").asObject();
        String username = selectedProfile.get("name").asString();
        String accessToken = response.get("accessToken").asString();
        UUID uuid = UUID.fromString(UUID_REGEX.matcher(selectedProfile.get("id").asString()).replaceFirst("$1-$2-$3-$4-$5"));
        String launcherToken = response.get("clientToken").asString();

        // We're done
        return new AuthlibAuthProviderResult(username, accessToken, uuid, launcherToken);
    }

    @Override
    public void close()
    {
        // Do nothing
    }

    /**
     * Класс, отвечающий за безопасность отправляемых данных
     * на сервер MineSocial.NET (ну хотя бы попытка)
     *
     * Функция предназначена для обертки пароля в SHA1,
     * где он сверяется с BCrypt на стороне сервиса
     *
     * Я не могу хранить данные в открытом виде, поэтому хотя бы так.
     **/

    // TODO: Сверить хеш после технических работ
    private static String getHash(String password)
    {
        try
        {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte[] array = md.digest(password.getBytes());
            StringBuilder sb = new StringBuilder();

            for (byte b : array) {
                sb.append(Integer.toHexString((b & 0xFF) | 0x100), 1, 3);
            }
            return sb.toString();
        }
        catch (NoSuchAlgorithmException e)
        {
            // Need?
            return null;
        }
    }
}