mirror of
https://github.com/Miasmusa/Shadow.git
synced 2024-11-28 10:15:52 -05:00
haha altening go brr
This commit is contained in:
parent
f695a937e8
commit
893cf37901
19 changed files with 831 additions and 6 deletions
|
@ -56,7 +56,6 @@ dependencies {
|
|||
|
||||
impl("meteordevelopment:discord-ipc:1.1")
|
||||
|
||||
impl(name: "xauthlib-1.0.0")
|
||||
impl 'org.java-websocket:Java-WebSocket:1.5.3'
|
||||
|
||||
configurations.impl.dependencies.each {
|
||||
|
|
Binary file not shown.
48
src/main/java/me/x150/authlib/AccountUtils.java
Normal file
48
src/main/java/me/x150/authlib/AccountUtils.java
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client/).
|
||||
* Copyright (c) 2021 Meteor Development.
|
||||
*/
|
||||
|
||||
package me.x150.authlib;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Base64;
|
||||
|
||||
public class AccountUtils {
|
||||
public static void setBaseUrl(YggdrasilMinecraftSessionService service, String url) {
|
||||
try {
|
||||
Field field = service.getClass().getDeclaredField("baseUrl");
|
||||
field.setAccessible(true);
|
||||
field.set(service, url);
|
||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setJoinUrl(YggdrasilMinecraftSessionService service, String url) {
|
||||
try {
|
||||
Field field = service.getClass().getDeclaredField("joinUrl");
|
||||
field.setAccessible(true);
|
||||
field.set(service, new URL(url));
|
||||
} catch (IllegalAccessException | NoSuchFieldException | MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setCheckUrl(YggdrasilMinecraftSessionService service, String url) {
|
||||
try {
|
||||
Field field = service.getClass().getDeclaredField("checkUrl");
|
||||
field.setAccessible(true);
|
||||
field.set(service, new URL(url));
|
||||
} catch (IllegalAccessException | NoSuchFieldException | MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
//
|
||||
// Source code recreated from a .class file by IntelliJ IDEA
|
||||
// (powered by FernFlower decompiler)
|
||||
//
|
||||
|
||||
package me.x150.authlib.exception;
|
||||
|
||||
public class AuthFailureException extends RuntimeException {
|
||||
public AuthFailureException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package me.x150.authlib.login.altening;
|
||||
|
||||
import com.mojang.authlib.Agent;
|
||||
import com.mojang.authlib.Environment;
|
||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
|
||||
import me.x150.authlib.AccountUtils;
|
||||
import me.x150.authlib.login.mojang.MinecraftToken;
|
||||
import net.minecraft.client.util.Session;
|
||||
import net.shadow.client.ShadowMain;
|
||||
import net.shadow.client.mixin.IMinecraftClientAccessor;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class AlteningAuth {
|
||||
private static final String AUTH = "http://authserver.thealtening.com";
|
||||
private static final String ACCOUNT = "https://api.mojang.com";
|
||||
private static final String SESSION = "http://sessionserver.thealtening.com";
|
||||
private static final String SERVICES = "https://api.minecraftservices.com";
|
||||
String username;
|
||||
String uuid;
|
||||
String token;
|
||||
private YggdrasilUserAuthentication getAuth() {
|
||||
YggdrasilUserAuthentication yggdrasilUserAuthentication = (YggdrasilUserAuthentication)new YggdrasilAuthenticationService(((IMinecraftClientAccessor) ShadowMain.client).getProxy(), "", Environment.create((String)"http://authserver.thealtening.com", (String)"https://api.mojang.com", (String)"http://sessionserver.thealtening.com", (String)"https://api.minecraftservices.com", (String)"The Altening")).createUserAuthentication(Agent.MINECRAFT);
|
||||
yggdrasilUserAuthentication.setUsername(token);
|
||||
yggdrasilUserAuthentication.setPassword("(REAL)");
|
||||
return yggdrasilUserAuthentication;
|
||||
}
|
||||
public AlteningAuth(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
public boolean fetchInfo() {
|
||||
YggdrasilUserAuthentication yggdrasilUserAuthentication = this.getAuth();
|
||||
try {
|
||||
yggdrasilUserAuthentication.logIn();
|
||||
this.username = yggdrasilUserAuthentication.getSelectedProfile().getName();
|
||||
this.uuid = yggdrasilUserAuthentication.getSelectedProfile().getId().toString();
|
||||
return true;
|
||||
}
|
||||
catch (AuthenticationException authenticationException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public MinecraftToken login() {
|
||||
fetchInfo();
|
||||
YggdrasilMinecraftSessionService yggdrasilMinecraftSessionService = (YggdrasilMinecraftSessionService) ShadowMain.client.getSessionService();
|
||||
AccountUtils.setBaseUrl(yggdrasilMinecraftSessionService, SESSION + "/session/minecraft/");
|
||||
AccountUtils.setJoinUrl(yggdrasilMinecraftSessionService, SESSION + "/session/minecraft/join");
|
||||
AccountUtils.setCheckUrl(yggdrasilMinecraftSessionService, SESSION + "/session/minecraft/hasJoined");
|
||||
YggdrasilUserAuthentication yggdrasilUserAuthentication = this.getAuth();
|
||||
try {
|
||||
yggdrasilUserAuthentication.logIn();
|
||||
((IMinecraftClientAccessor) ShadowMain.client).setSession(new Session(yggdrasilUserAuthentication.getSelectedProfile().getName(), yggdrasilUserAuthentication.getSelectedProfile().getId().toString(), yggdrasilUserAuthentication.getAuthenticatedToken(), Optional.empty(), Optional.empty(), Session.AccountType.MOJANG));
|
||||
this.username = yggdrasilUserAuthentication.getSelectedProfile().getName();
|
||||
return new MinecraftToken(yggdrasilUserAuthentication.getAuthenticatedToken(),username);
|
||||
}
|
||||
catch (AuthenticationException authenticationException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,297 @@
|
|||
|
||||
|
||||
package me.x150.authlib.login.microsoft;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import me.x150.authlib.exception.AuthFailureException;
|
||||
import me.x150.authlib.struct.Authenticator;
|
||||
|
||||
public class MicrosoftAuthenticator extends Authenticator<XboxToken> {
|
||||
protected final String clientId = "00000000402b5328";
|
||||
protected final String scopeUrl = "service::user.auth.xboxlive.com::MBI_SSL";
|
||||
protected String loginUrl;
|
||||
protected String loginCookie;
|
||||
protected String loginPPFT;
|
||||
|
||||
public MicrosoftAuthenticator() {
|
||||
}
|
||||
|
||||
public XboxToken login(String email, String password) {
|
||||
MicrosoftToken microsoftToken = this.generateTokenPair(this.generateLoginCode(email, password));
|
||||
XboxLiveToken xboxLiveToken = this.generateXboxTokenPair(microsoftToken);
|
||||
return this.generateXboxTokenPair(xboxLiveToken);
|
||||
}
|
||||
|
||||
private String generateLoginCode(String email, String password) {
|
||||
try {
|
||||
URL url = new URL("https://login.live.com/oauth20_authorize.srf?redirect_uri=https://login.live.com/oauth20_desktop.srf&scope=service::user.auth.xboxlive.com::MBI_SSL&display=touch&response_type=code&locale=en&client_id=00000000402b5328");
|
||||
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
|
||||
InputStream inputStream = httpURLConnection.getResponseCode() == 200 ? httpURLConnection.getInputStream() : httpURLConnection.getErrorStream();
|
||||
this.loginCookie = httpURLConnection.getHeaderField("set-cookie");
|
||||
String responseData = (String)(new BufferedReader(new InputStreamReader(inputStream))).lines().collect(Collectors.joining());
|
||||
Matcher bodyMatcher = Pattern.compile("sFTTag:[ ]?'.*value=\"(.*)\"/>'").matcher(responseData);
|
||||
if (bodyMatcher.find()) {
|
||||
this.loginPPFT = bodyMatcher.group(1);
|
||||
bodyMatcher = Pattern.compile("urlPost:[ ]?'(.+?(?='))").matcher(responseData);
|
||||
if (!bodyMatcher.find()) {
|
||||
throw new AuthFailureException("Authentication error. Could not find 'LOGIN-URL' tag from response!");
|
||||
} else {
|
||||
this.loginUrl = bodyMatcher.group(1);
|
||||
if (this.loginCookie != null && this.loginPPFT != null && this.loginUrl != null) {
|
||||
return this.sendCodeData(email, password);
|
||||
} else {
|
||||
throw new AuthFailureException("Authentication error. Error in authentication process!");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new AuthFailureException("Authentication error. Could not find 'LOGIN-PFTT' tag from response!");
|
||||
}
|
||||
} catch (IOException var8) {
|
||||
throw new AuthFailureException(String.format("Authentication error. Request could not be made! Cause: '%s'", var8.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private String sendCodeData(String email, String password) {
|
||||
Map<String, String> requestData = new HashMap();
|
||||
requestData.put("login", email);
|
||||
requestData.put("loginfmt", email);
|
||||
requestData.put("passwd", password);
|
||||
requestData.put("PPFT", this.loginPPFT);
|
||||
String postData = this.encodeURL((Map)requestData);
|
||||
|
||||
String authToken;
|
||||
try {
|
||||
byte[] data = postData.getBytes(StandardCharsets.UTF_8);
|
||||
HttpURLConnection connection = (HttpURLConnection)(new URL(this.loginUrl)).openConnection();
|
||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
|
||||
connection.setRequestProperty("Content-Length", String.valueOf(data.length));
|
||||
connection.setRequestProperty("Cookie", this.loginCookie);
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
|
||||
try {
|
||||
outputStream.write(data);
|
||||
} catch (Throwable var12) {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (Throwable var11) {
|
||||
var12.addSuppressed(var11);
|
||||
}
|
||||
}
|
||||
|
||||
throw var12;
|
||||
}
|
||||
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
if (connection.getResponseCode() != 200 || connection.getURL().toString().equals(this.loginUrl)) {
|
||||
throw new AuthFailureException("Authentication error. Username or password is not valid.");
|
||||
}
|
||||
|
||||
Pattern pattern = Pattern.compile("[?|&]code=([\\w.-]+)");
|
||||
Matcher tokenMatcher = pattern.matcher(URLDecoder.decode(connection.getURL().toString(), StandardCharsets.UTF_8.name()));
|
||||
if (!tokenMatcher.find()) {
|
||||
throw new AuthFailureException("Authentication error. Could not handle data from response.");
|
||||
}
|
||||
|
||||
authToken = tokenMatcher.group(1);
|
||||
} catch (IOException var13) {
|
||||
throw new AuthFailureException(String.format("Authentication error. Request could not be made! Cause: '%s'", var13.getMessage()));
|
||||
}
|
||||
|
||||
this.loginUrl = null;
|
||||
this.loginCookie = null;
|
||||
this.loginPPFT = null;
|
||||
return authToken;
|
||||
}
|
||||
|
||||
private void sendXboxRequest(HttpURLConnection httpURLConnection, JsonObject request, JsonObject properties) throws IOException {
|
||||
request.add("Properties", properties);
|
||||
String requestBody = request.toString();
|
||||
httpURLConnection.setFixedLengthStreamingMode(requestBody.length());
|
||||
httpURLConnection.setRequestProperty("Content-Type", "application/json");
|
||||
httpURLConnection.setRequestProperty("Accept", "application/json");
|
||||
httpURLConnection.connect();
|
||||
OutputStream outputStream = httpURLConnection.getOutputStream();
|
||||
|
||||
try {
|
||||
outputStream.write(requestBody.getBytes(StandardCharsets.US_ASCII));
|
||||
} catch (Throwable var9) {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (Throwable var8) {
|
||||
var9.addSuppressed(var8);
|
||||
}
|
||||
}
|
||||
|
||||
throw var9;
|
||||
}
|
||||
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private MicrosoftToken generateTokenPair(String authToken) {
|
||||
try {
|
||||
Map<String, String> arguments = new HashMap();
|
||||
arguments.put("client_id", "00000000402b5328");
|
||||
arguments.put("code", authToken);
|
||||
arguments.put("grant_type", "authorization_code");
|
||||
arguments.put("redirect_uri", "https://login.live.com/oauth20_desktop.srf");
|
||||
arguments.put("scope", "service::user.auth.xboxlive.com::MBI_SSL");
|
||||
StringJoiner argumentBuilder = new StringJoiner("&");
|
||||
Iterator var4 = arguments.entrySet().iterator();
|
||||
|
||||
while(var4.hasNext()) {
|
||||
Map.Entry<String, String> entry = (Map.Entry)var4.next();
|
||||
argumentBuilder.add(this.encodeURL((String)entry.getKey()) + "=" + this.encodeURL((String)entry.getValue()));
|
||||
}
|
||||
|
||||
byte[] data = argumentBuilder.toString().getBytes(StandardCharsets.UTF_8);
|
||||
URL url = new URL("https://login.live.com/oauth20_token.srf");
|
||||
URLConnection urlConnection = url.openConnection();
|
||||
HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
|
||||
httpURLConnection.setRequestMethod("POST");
|
||||
httpURLConnection.setDoOutput(true);
|
||||
httpURLConnection.setFixedLengthStreamingMode(data.length);
|
||||
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
httpURLConnection.connect();
|
||||
OutputStream outputStream = httpURLConnection.getOutputStream();
|
||||
|
||||
try {
|
||||
outputStream.write(data);
|
||||
} catch (Throwable var12) {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (Throwable var11) {
|
||||
var12.addSuppressed(var11);
|
||||
}
|
||||
}
|
||||
|
||||
throw var12;
|
||||
}
|
||||
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
JsonObject jsonObject = this.parseResponseData(httpURLConnection);
|
||||
return new MicrosoftToken(jsonObject.get("access_token").getAsString(), jsonObject.get("refresh_token").getAsString());
|
||||
} catch (IOException var13) {
|
||||
throw new AuthFailureException(String.format("Authentication error. Request could not be made! Cause: '%s'", var13.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public XboxLiveToken generateXboxTokenPair(MicrosoftToken microsoftToken) {
|
||||
try {
|
||||
URL url = new URL("https://user.auth.xboxlive.com/user/authenticate");
|
||||
URLConnection urlConnection = url.openConnection();
|
||||
HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
|
||||
httpURLConnection.setDoOutput(true);
|
||||
JsonObject request = new JsonObject();
|
||||
request.addProperty("RelyingParty", "http://auth.xboxlive.com");
|
||||
request.addProperty("TokenType", "JWT");
|
||||
JsonObject properties = new JsonObject();
|
||||
properties.addProperty("AuthMethod", "RPS");
|
||||
properties.addProperty("SiteName", "user.auth.xboxlive.com");
|
||||
properties.addProperty("RpsTicket", microsoftToken.getToken());
|
||||
this.sendXboxRequest(httpURLConnection, request, properties);
|
||||
JsonObject jsonObject = this.parseResponseData(httpURLConnection);
|
||||
String uhs = ((JsonObject)jsonObject.getAsJsonObject("DisplayClaims").getAsJsonArray("xui").get(0)).get("uhs").getAsString();
|
||||
return new XboxLiveToken(jsonObject.get("Token").getAsString(), uhs);
|
||||
} catch (IOException var9) {
|
||||
throw new AuthFailureException(String.format("Authentication error. Request could not be made! Cause: '%s'", var9.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public XboxToken generateXboxTokenPair(XboxLiveToken xboxLiveToken) {
|
||||
try {
|
||||
URL url = new URL("https://xsts.auth.xboxlive.com/xsts/authorize");
|
||||
URLConnection urlConnection = url.openConnection();
|
||||
HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
|
||||
httpURLConnection.setRequestMethod("POST");
|
||||
httpURLConnection.setDoOutput(true);
|
||||
JsonObject request = new JsonObject();
|
||||
request.addProperty("RelyingParty", "rp://api.minecraftservices.com/");
|
||||
request.addProperty("TokenType", "JWT");
|
||||
JsonObject properties = new JsonObject();
|
||||
properties.addProperty("SandboxId", "RETAIL");
|
||||
JsonArray userTokens = new JsonArray();
|
||||
userTokens.add(xboxLiveToken.getToken());
|
||||
properties.add("UserTokens", userTokens);
|
||||
this.sendXboxRequest(httpURLConnection, request, properties);
|
||||
if (httpURLConnection.getResponseCode() == 401) {
|
||||
throw new AuthFailureException("No xbox account was found!");
|
||||
} else {
|
||||
JsonObject jsonObject = this.parseResponseData(httpURLConnection);
|
||||
String uhs = ((JsonObject)jsonObject.getAsJsonObject("DisplayClaims").getAsJsonArray("xui").get(0)).get("uhs").getAsString();
|
||||
return new XboxToken(jsonObject.get("Token").getAsString(), uhs);
|
||||
}
|
||||
} catch (IOException var10) {
|
||||
throw new AuthFailureException(String.format("Authentication error. Request could not be made! Cause: '%s'", var10.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public JsonObject parseResponseData(HttpURLConnection httpURLConnection) throws IOException {
|
||||
BufferedReader bufferedReader;
|
||||
if (httpURLConnection.getResponseCode() != 200) {
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getErrorStream()));
|
||||
} else {
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
|
||||
}
|
||||
|
||||
String lines = (String)bufferedReader.lines().collect(Collectors.joining());
|
||||
JsonObject jsonObject = (new JsonParser()).parse(lines).getAsJsonObject();
|
||||
if (jsonObject.has("error")) {
|
||||
throw new AuthFailureException(jsonObject.get("error") + ": " + jsonObject.get("error_description"));
|
||||
} else {
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
|
||||
private String encodeURL(String url) {
|
||||
return URLEncoder.encode(url, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private String encodeURL(Map<String, String> map) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
Map.Entry entry;
|
||||
for(Iterator var3 = map.entrySet().iterator(); var3.hasNext(); sb.append(String.format("%s=%s", this.encodeURL((String)entry.getKey()), this.encodeURL((String)entry.getValue())))) {
|
||||
entry = (Map.Entry)var3.next();
|
||||
if (sb.length() > 0) {
|
||||
sb.append("&");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
|
||||
package me.x150.authlib.login.microsoft;
|
||||
|
||||
import me.x150.authlib.struct.AuthToken;
|
||||
|
||||
public class MicrosoftToken extends AuthToken {
|
||||
protected String token;
|
||||
protected String refreshToken;
|
||||
|
||||
public MicrosoftToken() {
|
||||
}
|
||||
|
||||
public MicrosoftToken(String token, String refreshToken) {
|
||||
this.token = token;
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return this.refreshToken;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
|
||||
package me.x150.authlib.login.microsoft;
|
||||
|
||||
import me.x150.authlib.struct.AuthToken;
|
||||
|
||||
public class XboxLiveToken extends AuthToken {
|
||||
protected String token;
|
||||
protected String uhs;
|
||||
|
||||
public XboxLiveToken() {
|
||||
}
|
||||
|
||||
public XboxLiveToken(String token, String uhs) {
|
||||
this.token = token;
|
||||
this.uhs = uhs;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
public String getUhs() {
|
||||
return this.uhs;
|
||||
}
|
||||
}
|
10
src/main/java/me/x150/authlib/login/microsoft/XboxToken.java
Normal file
10
src/main/java/me/x150/authlib/login/microsoft/XboxToken.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
package me.x150.authlib.login.microsoft;
|
||||
|
||||
public class XboxToken extends XboxLiveToken {
|
||||
public XboxToken() {
|
||||
}
|
||||
|
||||
public XboxToken(String token, String uhs) {
|
||||
super(token, uhs);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
package me.x150.authlib.login.mojang;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import me.x150.authlib.exception.AuthFailureException;
|
||||
import me.x150.authlib.login.altening.AlteningAuth;
|
||||
import me.x150.authlib.login.microsoft.MicrosoftAuthenticator;
|
||||
import me.x150.authlib.login.microsoft.XboxToken;
|
||||
import me.x150.authlib.login.mojang.MinecraftToken;
|
||||
import me.x150.authlib.login.mojang.profile.MinecraftProfile;
|
||||
import me.x150.authlib.login.mojang.profile.MinecraftProfileCape;
|
||||
import me.x150.authlib.login.mojang.profile.MinecraftProfileSkin;
|
||||
import me.x150.authlib.struct.Authenticator;
|
||||
|
||||
public class MinecraftAuthenticator extends Authenticator<MinecraftToken> {
|
||||
protected final MicrosoftAuthenticator microsoftAuthenticator = new MicrosoftAuthenticator();
|
||||
|
||||
public MinecraftAuthenticator() {
|
||||
}
|
||||
|
||||
public MinecraftToken login(String email, String password) {
|
||||
try {
|
||||
URL url = new URL("https://authserver.mojang.com/authenticate");
|
||||
URLConnection urlConnection = url.openConnection();
|
||||
HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
|
||||
httpURLConnection.setRequestMethod("POST");
|
||||
httpURLConnection.setDoOutput(true);
|
||||
JsonObject request = new JsonObject();
|
||||
JsonObject agent = new JsonObject();
|
||||
agent.addProperty("name", "Minecraft");
|
||||
agent.addProperty("version", "1");
|
||||
request.add("agent", agent);
|
||||
request.addProperty("username", email);
|
||||
request.addProperty("password", password);
|
||||
request.addProperty("requestUser", false);
|
||||
String requestBody = request.toString();
|
||||
httpURLConnection.setFixedLengthStreamingMode(requestBody.length());
|
||||
httpURLConnection.setRequestProperty("Content-Type", "application/json");
|
||||
httpURLConnection.setRequestProperty("Host", "authserver.mojang.com");
|
||||
httpURLConnection.connect();
|
||||
OutputStream outputStream = httpURLConnection.getOutputStream();
|
||||
|
||||
try {
|
||||
outputStream.write(requestBody.getBytes(StandardCharsets.US_ASCII));
|
||||
} catch (Throwable var13) {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (Throwable var12) {
|
||||
var13.addSuppressed(var12);
|
||||
}
|
||||
}
|
||||
|
||||
throw var13;
|
||||
}
|
||||
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
JsonObject jsonObject = this.parseResponseData(httpURLConnection);
|
||||
return new MinecraftToken(jsonObject.get("accessToken").getAsString(), ((JsonObject)jsonObject.get("selectedProfile")).get("name").getAsString());
|
||||
} catch (IOException var14) {
|
||||
throw new AuthFailureException(String.format("Authentication error. Request could not be made! Cause: '%s'", var14.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public MinecraftToken loginWithMicrosoft(String email, String password) {
|
||||
XboxToken xboxToken = this.microsoftAuthenticator.login(email, password);
|
||||
|
||||
try {
|
||||
URL url = new URL("https://api.minecraftservices.com/authentication/login_with_xbox");
|
||||
URLConnection urlConnection = url.openConnection();
|
||||
HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
|
||||
httpURLConnection.setRequestMethod("POST");
|
||||
httpURLConnection.setDoOutput(true);
|
||||
JsonObject request = new JsonObject();
|
||||
request.addProperty("identityToken", "XBL3.0 x=" + xboxToken.getUhs() + ";" + xboxToken.getToken());
|
||||
String requestBody = request.toString();
|
||||
httpURLConnection.setFixedLengthStreamingMode(requestBody.length());
|
||||
httpURLConnection.setRequestProperty("Content-Type", "application/json");
|
||||
httpURLConnection.setRequestProperty("Host", "api.minecraftservices.com");
|
||||
httpURLConnection.connect();
|
||||
OutputStream outputStream = httpURLConnection.getOutputStream();
|
||||
|
||||
try {
|
||||
outputStream.write(requestBody.getBytes(StandardCharsets.US_ASCII));
|
||||
} catch (Throwable var13) {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (Throwable var12) {
|
||||
var13.addSuppressed(var12);
|
||||
}
|
||||
}
|
||||
|
||||
throw var13;
|
||||
}
|
||||
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
JsonObject jsonObject = this.microsoftAuthenticator.parseResponseData(httpURLConnection);
|
||||
return new MinecraftToken(jsonObject.get("access_token").getAsString(), jsonObject.get("username").getAsString());
|
||||
} catch (IOException var14) {
|
||||
throw new AuthFailureException(String.format("Authentication error. Request could not be made! Cause: '%s'", var14.getMessage()));
|
||||
}
|
||||
}
|
||||
public MinecraftToken loginWithAltening(String token) {
|
||||
AlteningAuth alteningAuth = new AlteningAuth(token);
|
||||
return alteningAuth.login();
|
||||
}
|
||||
|
||||
public MinecraftProfile getGameProfile(MinecraftToken minecraftToken) {
|
||||
try {
|
||||
URL url = new URL("https://api.minecraftservices.com/minecraft/profile");
|
||||
URLConnection urlConnection = url.openConnection();
|
||||
HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
|
||||
httpURLConnection.setRequestMethod("GET");
|
||||
httpURLConnection.setRequestProperty("Authorization", "Bearer " + minecraftToken.getAccessToken());
|
||||
httpURLConnection.setRequestProperty("Host", "api.minecraftservices.com");
|
||||
httpURLConnection.connect();
|
||||
JsonObject jsonObject = this.parseResponseData(httpURLConnection);
|
||||
UUID uuid = this.generateUUID(jsonObject.get("id").getAsString());
|
||||
String name = jsonObject.get("name").getAsString();
|
||||
|
||||
return new MinecraftProfile(uuid, name);
|
||||
} catch (IOException var10) {
|
||||
throw new AuthFailureException(String.format("Authentication error. Request could not be made! Cause: '%s'", var10.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public JsonObject parseResponseData(HttpURLConnection httpURLConnection) throws IOException {
|
||||
BufferedReader bufferedReader;
|
||||
if (httpURLConnection.getResponseCode() != 200) {
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getErrorStream()));
|
||||
} else {
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
|
||||
}
|
||||
|
||||
String lines = (String)bufferedReader.lines().collect(Collectors.joining());
|
||||
JsonObject jsonObject = (JsonObject)this.gson.fromJson(lines, JsonObject.class);
|
||||
if (jsonObject.has("error")) {
|
||||
throw new AuthFailureException(String.format("Could not find profile!. Error: '%s'", jsonObject.get("errorMessage").getAsString()));
|
||||
} else {
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
|
||||
public UUID generateUUID(String trimmedUUID) throws IllegalArgumentException {
|
||||
if (trimmedUUID == null) {
|
||||
throw new IllegalArgumentException();
|
||||
} else {
|
||||
StringBuilder builder = new StringBuilder(trimmedUUID.trim());
|
||||
|
||||
try {
|
||||
builder.insert(20, "-");
|
||||
builder.insert(16, "-");
|
||||
builder.insert(12, "-");
|
||||
builder.insert(8, "-");
|
||||
return UUID.fromString(builder.toString());
|
||||
} catch (StringIndexOutOfBoundsException var4) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package me.x150.authlib.login.mojang;
|
||||
|
||||
public class MinecraftToken {
|
||||
private String accessToken;
|
||||
private String username;
|
||||
|
||||
public MinecraftToken() {
|
||||
}
|
||||
|
||||
public MinecraftToken(String accessToken, String username) {
|
||||
this.accessToken = accessToken;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return this.accessToken;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "MinecraftToken{accessToken='" + this.accessToken + '\'' + ", username='" + this.username + '\'' + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package me.x150.authlib.login.mojang.profile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MinecraftProfile {
|
||||
private UUID uuid;
|
||||
private String username;
|
||||
|
||||
public MinecraftProfile() {
|
||||
}
|
||||
|
||||
public MinecraftProfile(UUID uuid, String username) {
|
||||
this.uuid = uuid;
|
||||
this.username = username;
|
||||
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String toString() {
|
||||
return "MinecraftProfile{uuid=" + this.uuid + ", username='" + this.username + '\'' + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package me.x150.authlib.login.mojang.profile;
|
||||
|
||||
import me.x150.authlib.struct.OnlineTexture;
|
||||
|
||||
public class MinecraftProfileCape extends OnlineTexture {
|
||||
public MinecraftProfileCape() {
|
||||
}
|
||||
|
||||
public MinecraftProfileCape(String id, String state, String url, String alias) {
|
||||
super(id, state, url, alias);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package me.x150.authlib.login.mojang.profile;
|
||||
|
||||
import me.x150.authlib.struct.OnlineTexture;
|
||||
|
||||
public class MinecraftProfileSkin extends OnlineTexture {
|
||||
private String variant;
|
||||
|
||||
public MinecraftProfileSkin() {
|
||||
}
|
||||
|
||||
public MinecraftProfileSkin(String variant) {
|
||||
this.variant = variant;
|
||||
}
|
||||
|
||||
public MinecraftProfileSkin(String id, String state, String url, String alias, String variant) {
|
||||
super(id, state, url, alias);
|
||||
this.variant = variant;
|
||||
}
|
||||
|
||||
public String getVariant() {
|
||||
return this.variant;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "MinecraftSkin{id='" + this.getId() + '\'' + ", state='" + this.getState() + '\'' + ", url='" + this.getUrl() + '\'' + ", alias='" + this.getAlias() + '\'' + "variant='" + this.variant + '\'' + '}';
|
||||
}
|
||||
}
|
6
src/main/java/me/x150/authlib/struct/AuthToken.java
Normal file
6
src/main/java/me/x150/authlib/struct/AuthToken.java
Normal file
|
@ -0,0 +1,6 @@
|
|||
package me.x150.authlib.struct;
|
||||
|
||||
public abstract class AuthToken {
|
||||
public AuthToken() {
|
||||
}
|
||||
}
|
15
src/main/java/me/x150/authlib/struct/Authenticator.java
Normal file
15
src/main/java/me/x150/authlib/struct/Authenticator.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
package me.x150.authlib.struct;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import java.net.http.HttpClient;
|
||||
import java.time.Duration;
|
||||
|
||||
public abstract class Authenticator<T> {
|
||||
protected final Gson gson = new Gson();
|
||||
protected final HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10L)).build();
|
||||
|
||||
public Authenticator() {
|
||||
}
|
||||
|
||||
public abstract T login(String var1, String var2);
|
||||
}
|
38
src/main/java/me/x150/authlib/struct/OnlineTexture.java
Normal file
38
src/main/java/me/x150/authlib/struct/OnlineTexture.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
package me.x150.authlib.struct;
|
||||
|
||||
public abstract class OnlineTexture {
|
||||
private String id;
|
||||
private String state;
|
||||
private String url;
|
||||
private String alias;
|
||||
|
||||
public OnlineTexture() {
|
||||
}
|
||||
|
||||
public OnlineTexture(String id, String state, String url, String alias) {
|
||||
this.id = id;
|
||||
this.state = state;
|
||||
this.url = url;
|
||||
this.alias = alias;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
public String getAlias() {
|
||||
return this.alias;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "TextureVariable{id='" + this.id + '\'' + ", state='" + this.state + '\'' + ", url='" + this.url + '\'' + ", alias='" + this.alias + '\'' + '}';
|
||||
}
|
||||
}
|
|
@ -233,10 +233,12 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
|
|||
new Thread(() -> {
|
||||
this.selectedAlt.login();
|
||||
isLoggingIn.set(false);
|
||||
if (!this.selectedAlt.storage.valid) {
|
||||
// TODO: Actually fix this error instead of janky bypass
|
||||
if (!this.selectedAlt.storage.valid && this.selectedAlt.storage.type != AddScreenOverlay.AccountType.ALTENING) {
|
||||
HudNotification.create("Failed to log in", 5000, HudNotification.Type.ERROR);
|
||||
return;
|
||||
}
|
||||
if(this.selectedAlt.storage.type == AddScreenOverlay.AccountType.ALTENING) return;
|
||||
Session newSession = new Session(selectedAlt.storage.cachedName, selectedAlt.storage.cachedUuid.toString(), selectedAlt.storage.accessToken, Optional.empty(), Optional.empty(), Session.AccountType.MOJANG);
|
||||
((IMinecraftClientAccessor) ShadowMain.client).setSession(newSession);
|
||||
HudNotification.create("Logged into account " + newSession.getUsername(), 5000, HudNotification.Type.INFO);
|
||||
|
@ -337,7 +339,7 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
|
|||
RenderSystem.defaultBlendFunc();
|
||||
|
||||
String mail;
|
||||
if (this.selectedAlt.storage.type != AddScreenOverlay.AccountType.CRACKED) {
|
||||
if (this.selectedAlt.storage.type != AddScreenOverlay.AccountType.CRACKED || this.selectedAlt.storage.type != AddScreenOverlay.AccountType.ALTENING) {
|
||||
mail = this.selectedAlt.storage.email;
|
||||
String[] mailPart = mail.split("@");
|
||||
String domain = mailPart[mailPart.length - 1];
|
||||
|
@ -671,7 +673,7 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
|
|||
protected void init() {
|
||||
RoundButton exit = new net.shadow.client.feature.gui.widget.RoundButton(net.shadow.client.feature.gui.widget.RoundButton.STANDARD, width - 20 - 5, 5, 20, 20, "X", () -> Objects.requireNonNull(client).setScreen(parent));
|
||||
buttons.add(exit);
|
||||
email = new RoundTextFieldWidget(width / 2d - (widgetWid - padding * 2) / 2d, height / 2d - widgetHei / 2d + padding, widgetWid - padding * 2, 20, "E-Mail or username");
|
||||
email = new RoundTextFieldWidget(width / 2d - (widgetWid - padding * 2) / 2d, height / 2d - widgetHei / 2d + padding, widgetWid - padding * 2, 20, "E-Mail or username or Token");
|
||||
passwd = new RoundTextFieldWidget(width / 2d - (widgetWid - padding * 2) / 2d, height / 2d - widgetHei / 2d + padding * 2 + 20, widgetWid - padding * 2, 20, "Password");
|
||||
type = new net.shadow.client.feature.gui.widget.RoundButton(net.shadow.client.feature.gui.widget.RoundButton.STANDARD, 0, 0, widgetWid / 2d - padding * 1.5, 20, "Type: " + AccountType.values()[accountTypeI].s, this::cycle);
|
||||
add = new net.shadow.client.feature.gui.widget.RoundButton(net.shadow.client.feature.gui.widget.RoundButton.STANDARD, 0, 0, widgetWid / 2d - padding * 1.5, 20, "Add", this::add);
|
||||
|
@ -687,7 +689,7 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
|
|||
}
|
||||
|
||||
boolean isAddApplicable() {
|
||||
if (AccountType.values()[accountTypeI] == AccountType.CRACKED && !email.getText().isEmpty()) {
|
||||
if (AccountType.values()[accountTypeI] == AccountType.CRACKED ||AccountType.values()[accountTypeI] == AccountType.ALTENING && !email.getText().isEmpty()) {
|
||||
return true;
|
||||
} else {
|
||||
return !email.getText().isEmpty() && !passwd.getText().isEmpty();
|
||||
|
@ -776,7 +778,7 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
|
|||
}
|
||||
|
||||
enum AccountType {
|
||||
MOJANG("Mojang"), MICROSOFT("Microsoft"), CRACKED("Cracked");
|
||||
MOJANG("Mojang"), MICROSOFT("Microsoft"), CRACKED("Cracked"), ALTENING("The Altening");
|
||||
|
||||
final String s;
|
||||
|
||||
|
@ -828,6 +830,7 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
|
|||
case MOJANG -> auth.login(storage.email, storage.password);
|
||||
case MICROSOFT -> auth.loginWithMicrosoft(storage.email, storage.password);
|
||||
case CRACKED -> null;
|
||||
case ALTENING -> auth.loginWithAltening(storage.email);
|
||||
};
|
||||
if (token == null && storage.password.equals("")) {
|
||||
storage.valid = true;
|
||||
|
@ -840,9 +843,11 @@ public class AltManagerScreen extends ClientScreen implements FastTickable {
|
|||
throw new NullPointerException();
|
||||
}
|
||||
storage.accessToken = token.getAccessToken();
|
||||
|
||||
MinecraftProfile profile = auth.getGameProfile(token);
|
||||
storage.cachedName = profile.getUsername();
|
||||
storage.cachedUuid = profile.getUuid();
|
||||
|
||||
downloadTexture();
|
||||
storage.valid = true;
|
||||
} catch (Exception ignored) {
|
||||
|
|
|
@ -11,6 +11,8 @@ import org.spongepowered.asm.mixin.Mixin;
|
|||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.net.Proxy;
|
||||
|
||||
@Mixin(MinecraftClient.class)
|
||||
public interface IMinecraftClientAccessor {
|
||||
|
||||
|
@ -20,4 +22,6 @@ public interface IMinecraftClientAccessor {
|
|||
|
||||
@Accessor("renderTickCounter")
|
||||
RenderTickCounter getRenderTickCounter();
|
||||
@Accessor("networkProxy")
|
||||
Proxy getProxy();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue