package pl.asiekierka.AsieLauncher.auth;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.UUID;
import javax.net.ssl.HttpsURLConnection;
import org.json.simple.*;
import org.json.simple.parser.*;
import pl.asiekierka.AsieLauncher.common.Utils;
public class AuthenticationYggdrasil extends Authentication {
// Special thanks to the MinecraftCoalition. (wiki.vg)
private static final String SERVER = "https://authserver.mojang.com";
private String filename, directory;
private boolean triedRenewSessionID, keepLoggedIn;
private JSONObject info;
@SuppressWarnings("unchecked")
public AuthenticationYggdrasil(String _directory, boolean _keepLoggedIn) {
directory = _directory;
triedRenewSessionID = false;
keepLoggedIn = _keepLoggedIn;
filename = directory + "yggdrasil.json";
info = Utils.readJSONFile(filename);
if(info == null) {
info = new JSONObject();
}
if(get("clientToken") == null) {
// Generate client token
info.put("clientToken", UUID.randomUUID().toString());
save();
}
}
private void save() {
Utils.saveStringToFile(filename, info.toJSONString());
}
private String get(String name) { return info.containsKey(name) ? (String)info.get(name) : null; }
@SuppressWarnings("unchecked")
public void setKeepPassword(boolean l) {
if(keepLoggedIn == true && l == false) {
sessionID = null;
info.put("sessionID", null);
}
keepLoggedIn = l;
}
private String readIn(BufferedReader in) {
try {
String answer = "";
String inputLine = in.readLine();
while(inputLine != null) {
answer += inputLine;
inputLine = in.readLine();
}
in.close();
return answer;
} catch(Exception e) { return ""; }
}
@SuppressWarnings("unchecked")
private JSONObject sendJSONPayload(String path, JSONObject payload) {
HttpsURLConnection con = null;
try {
if(!payload.containsKey("agent")) {
JSONObject agent = new JSONObject();
agent.put("name", "Minecraft");
agent.put("version", 1);
payload.put("agent", agent);
}
URL url = new URL(SERVER + path);
con = (HttpsURLConnection)url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setDoOutput(true);
DataOutputStream dos = new DataOutputStream(con.getOutputStream());
dos.writeBytes(payload.toJSONString());
dos.flush();
dos.close();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
return (JSONObject)new JSONParser().parse(readIn(in));
}
catch(IOException ioe) {
try {
if(con == null) throw new Exception("Connection not initialized here");
else {
BufferedReader in = new BufferedReader(new InputStreamReader(con.getErrorStream()));
return (JSONObject)new JSONParser().parse(readIn(in));
}
} catch(Exception e) {
e.printStackTrace(); error = "Internal AsieLauncher error"; return null;
}
}
catch(Exception e) {
e.printStackTrace(); error = "Internal AsieLauncher error"; return null;
}
}
private int handlingError(JSONObject errorJSON) {
if(errorJSON == null) {
error = "Server error!";
return SERVER_DOWN;
}
if(!errorJSON.containsKey("error")) return OK;
if(errorJSON.containsKey("errorMessage")) error = (String)errorJSON.get("errorMessage");
else error = (String)errorJSON.get("error");
return LOGIN_INVALID;
}
@SuppressWarnings("unchecked")
private boolean renewSessionID() {
triedRenewSessionID = true;
sessionID = get("sessionID");
if(sessionID == null || !info.containsKey("selectedProfile")) {
// No Session ID or profile found!
return false;
}
// Session ID is stored, attempt renewing.
JSONObject payload = new JSONObject();
payload.put("accessToken", sessionID);
payload.put("clientToken", get("clientToken"));
//payload.put("selectedProfile", null);
JSONObject answer = sendJSONPayload("/refresh", payload);
if(handlingError(answer) != OK) {
sessionID = null;
return false;
}
JSONObject profile = (JSONObject)answer.get("selectedProfile");
realUsername = (String)profile.get("name");
sessionID = (String)answer.get("accessToken");
_UUID = (String)profile.get("id");
if(keepLoggedIn) {
info.put("sessionID", sessionID);
save();
}
return true;
}
@Override
public String getSessionToken() {
if(!info.containsKey("selectedProfile")) return null;
JSONObject profile = (JSONObject)info.get("selectedProfile");
//return "token:"+sessionID+":"+(String)profile.get("id");
return sessionID;
}
@Override
public boolean requiresPassword() {
if(!triedRenewSessionID) return !renewSessionID();
else return true;
}
@SuppressWarnings("unchecked")
@Override
public int authenticate(String username, String password) {
if(triedRenewSessionID && sessionID != null && sessionID.length() > 0) {
return OK; // Already authenticated, don't bother.
}
realUsername = username; // For now.
JSONObject payload = new JSONObject();
payload.put("username", username);
payload.put("password", password);
payload.put("clientToken", get("clientToken"));
JSONObject answer = sendJSONPayload("/authenticate", payload);
if(handlingError(answer) != OK) return handlingError(answer);
JSONObject profile = (JSONObject)answer.get("selectedProfile");
realUsername = (String)profile.get("name");
sessionID = (String)answer.get("accessToken");
_UUID = (String)profile.get("id");
info.put("selectedProfile", profile);
if(keepLoggedIn) {
info.put("sessionID", sessionID);
save();
}
return OK;
}
}