Disable Mojang login (#331)

Merging early because... why not. Anyone that hasn't migrated now will get the warning.

Co-authored-by: Duy Tran Khanh <[email protected]>
This commit is contained in:
Adam TunnicandDuy Tran Khanh authored and GitHub committed 2022-03-09 19:03:08 -05:00
1 parent b24033e97b
commit 81ae236181
21 files changed
+36 -472

No files matched your search

@@ -1,65 +0,0 @@
package net.kdt.pojavlaunch;
import com.google.gson.JsonSyntaxException;
import java.io.File;
import java.io.IOException;
import net.kdt.pojavlaunch.authenticator.mojang.RefreshTokenTask;
import net.kdt.pojavlaunch.value.MinecraftAccount;
public class PojavProfile
{
/*
public static MinecraftAccount getCurrentProfileContent() throws IOException, JsonSyntaxException {
MinecraftAccount build = MinecraftAccount.load(getCurrentProfileName());
if (build == null) {
return getTempProfileContent();
}
return MinecraftAccount.load(getCurrentProfileName());
}
public static MinecraftAccount getTempProfileContent(Context ctx) {
return MinecraftAccount.parse(getPrefs(ctx).getString(PROFILE_PREF_TEMP_CONTENT, ""));
}
public static String getCurrentProfileName() {
String name = "";
try {
name = Tools.read(currAccFile.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
// A dirty fix
if (!name.isEmpty() && name.startsWith(Tools.DIR_ACCOUNT_NEW) && name.endsWith(".json")) {
name = name.substring(0, name.length() - 5).replace(Tools.DIR_ACCOUNT_NEW, "").replace(".json", "");
setCurrentProfile(name);
}
return name;
}
public static boolean setCurrentProfile(Object obj) {
try {
if (obj instanceof MinecraftAccount) {
throw new UnsupportedOperationException("Temp account is not supported yet");
} else if (obj instanceof String) {
String acc = (String) obj;
Tools.write(currAccFile.getAbsolutePath(), acc);
MinecraftAccount.clearTempAccount();
} else if (obj == null) {
// pref.putString(PROFILE_PREF_FILE, "");
} else {
throw new IllegalArgumentException("Profile must be MinecraftAccount.class, String.class or null");
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public static boolean isFileType() {
return new File(Tools.DIR_ACCOUNT_NEW + "/" + getCurrentProfileName() + ".json").exists();
}
*/
public static void updateTokens(final String name) throws Throwable {
new RefreshTokenTask().run(name);
}
}
@@ -193,7 +193,7 @@ public final class Tools
varArgMap.put("game_assets", Tools.ASSETS_PATH);
varArgMap.put("game_directory", gameDir.getAbsolutePath());
varArgMap.put("user_properties", "{}");
varArgMap.put("user_type", profile.isMicrosoft ? "msa" : "mojang");
varArgMap.put("user_type", "msa");
varArgMap.put("version_name", versionName);
varArgMap.put("version_type", versionInfo.type);
@@ -2,19 +2,17 @@ package net.kdt.pojavlaunch.authenticator.microsoft;
import android.util.*;
import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import net.kdt.pojavlaunch.*;
import net.kdt.pojavlaunch.authenticator.mojang.*;
import net.kdt.pojavlaunch.authenticator.microsoft.*;
import org.json.*;
import java.text.ParseException;
import java.io.*;
import net.kdt.pojavlaunch.*;
import net.kdt.pojavlaunch.value.launcherprofiles.*;
import net.kdt.pojavlaunch.value.*;
import org.json.*;
public class MicrosoftAuthTask {
//private Gson gson = new Gson();
@@ -44,14 +42,12 @@ public class MicrosoftAuthTask {
acc.accessToken = msa.mcToken;
acc.username = msa.mcName;
acc.profileId = msa.mcUuid;
acc.isMicrosoft = true;
acc.msaRefreshToken = msa.msRefreshToken;
} else if(msa.doesDemo) {
acc.clientToken = "0"; /* FIXME */
acc.accessToken = "-1"; // Differentiate from local accounts
acc.username = "demo_user";
acc.profileId = "25e00594-cf57-3f87-b3af-3f06591be252";
acc.isMicrosoft = false;
acc.msaRefreshToken = "0";
}
acc.save();
@@ -1,23 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang;
import java.io.File;
import java.util.UUID;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.authenticator.mojang.yggdrasil.YggdrasilAuthenticator;
import net.kdt.pojavlaunch.value.MinecraftAccount;
public class InvalidateTokenTask {
private YggdrasilAuthenticator authenticator = new YggdrasilAuthenticator();
//private Gson gson = new Gson();
private MinecraftAccount profilePath;
private String name;
public void run(String name) throws Throwable {
this.name = name;
this.profilePath = MinecraftAccount.load(name);
this.authenticator.invalidate(profilePath.accessToken,
UUID.fromString(profilePath.isMicrosoft ? profilePath.profileId : profilePath.clientToken /* should be? */));
new File(Tools.DIR_ACCOUNT_NEW, name + ".json").delete();
}
}
@@ -1,36 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang;
import java.io.File;
import java.util.UUID;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.authenticator.mojang.yggdrasil.AuthenticateResponse;
import net.kdt.pojavlaunch.authenticator.mojang.yggdrasil.YggdrasilAuthenticator;
import net.kdt.pojavlaunch.value.MinecraftAccount;
public class LoginTask {
private YggdrasilAuthenticator authenticator = new YggdrasilAuthenticator();
//private String TAG = "MojangAuth-login";
private UUID getRandomUUID() {
return UUID.randomUUID();
}
public MinecraftAccount run(String username, String password) throws Throwable {
AuthenticateResponse response = authenticator.authenticate(username, password, getRandomUUID());
if (response.selectedProfile == null) {
throw new IllegalArgumentException("Can't login a demo account!\n");
} else {
if (new File(Tools.DIR_ACCOUNT_NEW + "/" + response.selectedProfile.name + ".json").exists()) {
throw new IllegalArgumentException("This account already exist!\n");
} else {
MinecraftAccount acc = new MinecraftAccount();
acc.accessToken = response.accessToken;
acc.clientToken = response.clientToken.toString();
acc.profileId = response.selectedProfile.id;
acc.username = response.selectedProfile.name;
acc.save();
return acc;
}
}
}
}
@@ -1,38 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang;
import com.google.gson.*;
import java.util.*;
import net.kdt.pojavlaunch.*;
import net.kdt.pojavlaunch.authenticator.mojang.yggdrasil.*;
import net.kdt.pojavlaunch.value.*;
import java.io.IOException;
public class RefreshTokenTask {
private YggdrasilAuthenticator authenticator = new YggdrasilAuthenticator();
private MinecraftAccount profilePath;
public void run(String name) throws Throwable {
this.profilePath = MinecraftAccount.load(name);
int responseCode = 400;
try {
responseCode = this.authenticator.validate(profilePath.accessToken).statusCode;
} catch(RuntimeException e) {}
if (responseCode == 403) {
RefreshResponse response = this.authenticator.refresh(profilePath.accessToken, UUID.fromString(profilePath.clientToken));
if (response == null) {
// Refresh when offline?
return;
} else if (response.selectedProfile == null) {
throw new IllegalArgumentException("Can't refresh a demo account!");
}
profilePath.clientToken = response.clientToken.toString();
profilePath.accessToken = response.accessToken;
profilePath.username = response.selectedProfile.name;
profilePath.profileId = response.selectedProfile.id;
}
profilePath.save();
}
}
@@ -1,24 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil;
import java.util.UUID;
public class AuthenticateRequest {
public AgentInfo agent = new AgentInfo();
public UUID clientToken;
public String password;
public String username;
public static class AgentInfo {
public String name;
public int version;
}
public AuthenticateRequest(String username, String password, UUID clientToken, String clientName, int clientVersion) {
this.username = username;
this.password = password;
this.clientToken = clientToken;
this.agent.name = clientName;
this.agent.version = clientVersion;
}
}
@@ -1,11 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil;
import java.util.UUID;
public class AuthenticateResponse {
public String accessToken;
public Profile[] availableProfiles;
public UUID clientToken;
public Profile selectedProfile;
}
@@ -1,8 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil;
public class ErrorResponse {
public String cause;
public String error;
public String errorMessage;
}
@@ -1,23 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil;
import java.util.*;
public class NetworkResponse
{
public final int statusCode;
public final Object response;
public NetworkResponse(int statusCode, Object response) {
this.statusCode = statusCode;
this.response = response;
}
public void throwExceptionIfNeed(String msg) {
if (statusCode < 200 || statusCode >= 300) {
throw new RuntimeException(msg);
}
}
public void throwExceptionIfNeed() {
throwExceptionIfNeed("Respone error, code: " + statusCode + ", message: " + response);
}
}
@@ -1,8 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil;
public class Profile {
public String id;
public boolean legacy;
public String name;
}
@@ -1,14 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil;
import java.util.UUID;
public class RefreshRequest {
public String accessToken;
public UUID clientToken;
public RefreshRequest(String accessToken, UUID clientToken) {
this.accessToken = accessToken;
this.clientToken = clientToken;
}
}
@@ -1,10 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil;
import java.util.UUID;
public class RefreshResponse {
public String accessToken;
public UUID clientToken;
public Profile selectedProfile;
}
@@ -1,124 +0,0 @@
package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil;
import java.io.*;
import java.net.*;
import java.nio.charset.*;
import java.util.*;
import net.kdt.pojavlaunch.*;
public class YggdrasilAuthenticator {
private static final String API_URL = "https://authserver.mojang.com/";
private String clientName = "Minecraft";
private int clientVersion = 1;
private NetworkResponse makeRequest(String endpoint, Object inputObject, Class<?> responseClass) throws IOException, Throwable {
Throwable th;
InputStream is = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
String requestJson = Tools.GLOBAL_GSON.toJson(inputObject);
try {
URL url = new URL(API_URL + endpoint);
OutputStream os;
try {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("User-Agent", "Minecraft");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("charset", "utf-8");
conn.setRequestProperty("Content-Length", Integer.toString(requestJson.getBytes("UTF-8").length));
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.connect();
os = null;
os = conn.getOutputStream();
os.write(requestJson.getBytes(Charset.forName("UTF-8")));
if (os != null) {
os.close();
}
int statusCode = conn.getResponseCode();
if (statusCode != 200) {
is = conn.getErrorStream();
} else {
is = conn.getInputStream();
}
if (is != null) {
Tools.copy(is, bos);
try {
is.close();
} catch (Exception e) {
throw e;
}
}
String outString = new String(bos.toByteArray(), Charset.forName("UTF-8"));
if (statusCode == 200 || statusCode == 204){
System.out.println("Task " + endpoint + " successful");
if (responseClass != null) {
return new NetworkResponse(statusCode, Tools.GLOBAL_GSON.fromJson(outString, responseClass));
}
} else {
System.out.println("Task " + endpoint + " failure");
}
return new NetworkResponse(statusCode, outString);
} catch (UnknownHostException e) {
if (endpoint.equals("refresh")) {
return null;
} else {
throw new RuntimeException("Can't connect to the server", e);
}
} catch (Throwable th2) {
th = th2;
if (is != null) {
try {
is.close();
} catch (Exception e2) {
e2.addSuppressed(th2);
throw e2;
}
}
throw th;
}
} catch (Throwable th3) {
th = th3;
if (is != null) {
is.close();
}
throw th;
}
}
public AuthenticateResponse authenticate(String username, String password, UUID clientId) throws IOException, Throwable {
NetworkResponse obj = makeRequest("authenticate", new AuthenticateRequest(username, password, clientId, this.clientName, this.clientVersion), AuthenticateResponse.class);
/*
if (obj.statusCode != 200) {
throw new RuntimeException("Invalid username or password, status code: " + obj.statusCode);
}
*/
obj.throwExceptionIfNeed();
return (AuthenticateResponse) obj.response;
}
public RefreshResponse refresh(String authToken, UUID clientId) throws IOException, Throwable {
NetworkResponse obj = makeRequest("refresh", new RefreshRequest(authToken, clientId), RefreshResponse.class);
if (obj == null) {
return null;
} else {
obj.throwExceptionIfNeed(); // "Invalid username or password, status code: " + obj.statusCode);
return (RefreshResponse) obj.response;
}
}
public NetworkResponse validate(String authToken) throws Throwable {
return makeRequest("validate", new RefreshRequest(authToken, null), null);
}
public NetworkResponse invalidate(String authToken, UUID clientId) throws Throwable {
return makeRequest("invalidate", new RefreshRequest(authToken, clientId), null);
}
}
@@ -1,18 +1,14 @@
package net.kdt.pojavlaunch.uikit;
import java.net.UnknownHostException;
import net.kdt.pojavlaunch.PojavProfile;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.authenticator.microsoft.MicrosoftAuthTask;
import net.kdt.pojavlaunch.authenticator.mojang.LoginTask;
import net.kdt.pojavlaunch.authenticator.mojang.yggdrasil.*;
import net.kdt.pojavlaunch.value.MinecraftAccount;
public class AccountJNI {
public static final int TYPE_SELECTACC = 0;
public static final int TYPE_MICROSOFT = 1;
public static final int TYPE_MOJANG = 2;
public static final int TYPE_OFFLINE = 3;
public static final int TYPE_OFFLINE = 2;
public static volatile MinecraftAccount CURRENT_ACCOUNT;
@@ -20,7 +16,6 @@ public class AccountJNI {
public static String loginAccount(int type,
String data // One of:
// Local username
// Mojang json response
// Microsoft token
) {
try {
@@ -28,10 +23,8 @@ public class AccountJNI {
case TYPE_SELECTACC:
CURRENT_ACCOUNT = MinecraftAccount.load(data);
try {
if (CURRENT_ACCOUNT.isMicrosoft) {
if (CURRENT_ACCOUNT.accessToken.length() > 5) {
CURRENT_ACCOUNT = new MicrosoftAuthTask().run("true", CURRENT_ACCOUNT.msaRefreshToken);
} else if (CURRENT_ACCOUNT.accessToken.length() > 5) {
PojavProfile.updateTokens(data);
}
CURRENT_ACCOUNT = MinecraftAccount.load(data);
} catch (UnknownHostException e) {
@@ -44,16 +37,6 @@ public class AccountJNI {
CURRENT_ACCOUNT = new MicrosoftAuthTask().run("false", data);
break;
case TYPE_MOJANG:
AuthenticateResponse response = Tools.GLOBAL_GSON.fromJson(data, AuthenticateResponse.class);
CURRENT_ACCOUNT = new MinecraftAccount();
CURRENT_ACCOUNT.accessToken = response.accessToken;
CURRENT_ACCOUNT.clientToken = response.clientToken.toString();
CURRENT_ACCOUNT.profileId = response.selectedProfile.id;
CURRENT_ACCOUNT.username = response.selectedProfile.name;
CURRENT_ACCOUNT.save();
break;
case TYPE_OFFLINE:
CURRENT_ACCOUNT = new MinecraftAccount();
CURRENT_ACCOUNT.username = data;
@@ -10,7 +10,6 @@ public class MinecraftAccount
public String profileId = "00000000-0000-0000-0000-000000000000"; // authenticate UUID
public String username = "Steve";
public String selectedVersion = "1.7.10";
public boolean isMicrosoft = false;
public String msaRefreshToken = "0";
public String save(String outPath) throws IOException {