Replaced insecure Minecraft account authentication with server join technique
This commit is contained in:
@@ -4,12 +4,15 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||
import eu.crushedpixel.replaymod.api.mojang.MojangApiMethods;
|
||||
import eu.crushedpixel.replaymod.api.mojang.holders.Profile;
|
||||
import eu.crushedpixel.replaymod.api.replay.ReplayModApiMethods;
|
||||
import eu.crushedpixel.replaymod.api.replay.SearchQuery;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.*;
|
||||
import eu.crushedpixel.replaymod.online.authentication.AuthenticationHash;
|
||||
import eu.crushedpixel.replaymod.utils.StreamTools;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
@@ -24,6 +27,7 @@ import java.util.UUID;
|
||||
|
||||
public class ApiClient {
|
||||
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
private static final Gson gson = new Gson();
|
||||
private static final JsonParser jsonParser = new JsonParser();
|
||||
|
||||
@@ -36,18 +40,32 @@ public class ApiClient {
|
||||
return auth;
|
||||
}
|
||||
|
||||
public AuthKey register(String username, String mail, String password, String uuid, String accessToken)
|
||||
throws IOException, ApiException {
|
||||
public AuthKey register(String username, String mail, String password, String uuid)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
|
||||
AuthenticationHash authenticationHash = sessionserverJoin();
|
||||
|
||||
QueryBuilder builder = new QueryBuilder(ReplayModApiMethods.register);
|
||||
builder.put("username", username);
|
||||
builder.put("email", mail);
|
||||
builder.put("password", password);
|
||||
builder.put("uuid", uuid);
|
||||
builder.put("accesstoken", accessToken);
|
||||
builder.put("mcusername", authenticationHash.username);
|
||||
builder.put("timelong", authenticationHash.currentTime);
|
||||
builder.put("randomlong", authenticationHash.randomLong);
|
||||
AuthKey auth = invokeAndReturn(builder, AuthKey.class);
|
||||
return auth;
|
||||
}
|
||||
|
||||
private AuthenticationHash sessionserverJoin() throws AuthenticationException {
|
||||
AuthenticationHash hash = new AuthenticationHash();
|
||||
|
||||
mc.getSessionService().joinServer(
|
||||
mc.getSession().getProfile(), mc.getSession().getToken(), hash.hash);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public AuthConfirmation checkAuthkey(String auth) {
|
||||
try {
|
||||
QueryBuilder builder = new QueryBuilder(ReplayModApiMethods.check_authkey);
|
||||
|
||||
@@ -3,5 +3,6 @@ package eu.crushedpixel.replaymod.api.mojang;
|
||||
public class MojangApiMethods {
|
||||
|
||||
public static final String userprofile = "https://sessionserver.mojang.com/session/minecraft/profile/";
|
||||
public static final String joinServer = "https://sessionserver.mojang.com/session/minecraft/join";
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.gui.online;
|
||||
|
||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||
import eu.crushedpixel.replaymod.api.ApiException;
|
||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||
import eu.crushedpixel.replaymod.gui.PasswordTextField;
|
||||
@@ -196,6 +197,9 @@ public class GuiRegister extends GuiScreen {
|
||||
});
|
||||
} catch(ApiException ae) {
|
||||
message = ae.getLocalizedMessage();
|
||||
} catch(AuthenticationException aue) {
|
||||
aue.printStackTrace();
|
||||
message = I18n.format("replaymod.gui.register.error.authfailed");
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
message = I18n.format("replaymod.gui.login.connectionerror");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.online.authentication;
|
||||
|
||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.ApiClient;
|
||||
import eu.crushedpixel.replaymod.api.ApiException;
|
||||
@@ -36,10 +37,10 @@ public class AuthenticationHandler {
|
||||
|
||||
private static Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
public static void register(String usrname, String mail, String password) throws IOException, ApiException {
|
||||
public static void register(String usrname, String mail, String password)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
AuthKey auth = apiClient.register(usrname, mail, password,
|
||||
mc.getSession().getProfile().getId().toString(),
|
||||
Minecraft.getMinecraft().getSession().getToken());
|
||||
mc.getSession().getProfile().getId().toString());
|
||||
username = usrname;
|
||||
authkey = auth.getAuthkey();
|
||||
saveAuthkey(authkey);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package eu.crushedpixel.replaymod.online.authentication;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class AuthenticationHash {
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
public AuthenticationHash() {
|
||||
username = Minecraft.getMinecraft().getSession().getUsername();
|
||||
currentTime = System.currentTimeMillis();
|
||||
randomLong = random.nextLong();
|
||||
hash = getAuthenticationHash();
|
||||
}
|
||||
|
||||
public final String username;
|
||||
public final long currentTime;
|
||||
public final long randomLong;
|
||||
public final String hash;
|
||||
|
||||
private String getAuthenticationHash() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(username);
|
||||
builder.append(currentTime);
|
||||
builder.append(randomLong);
|
||||
|
||||
String md5 = builder.toString();
|
||||
|
||||
try {
|
||||
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
|
||||
byte[] array = md.digest(md5.getBytes());
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < array.length; ++i) {
|
||||
sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (java.security.NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -112,6 +112,7 @@ replaymod.gui.register.confirmpw=Confirm Password
|
||||
replaymod.gui.register.error.nomatch=Passwords don't match
|
||||
replaymod.gui.register.error.shortusername=Username has to be at least 5 characters long
|
||||
replaymod.gui.register.error.shortpw=Password has to be at least 5 characters long
|
||||
replaymod.gui.register.error.authfailed=Could not authenticate your Minecraft account
|
||||
|
||||
|
||||
#Replay Viewer GUI
|
||||
|
||||
Reference in New Issue
Block a user