Advertisement
Guest User

Untitled

a guest
Oct 15th, 2019
2,781
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.29 KB | None | 0 0
  1. package net.VytskaLT.BananaProxy.network.auth;
  2.  
  3. import com.fasterxml.jackson.core.type.TypeReference;
  4. import com.fasterxml.jackson.databind.JsonNode;
  5. import com.fasterxml.jackson.databind.node.ArrayNode;
  6. import com.fasterxml.jackson.databind.node.ObjectNode;
  7. import com.nukkitx.protocol.bedrock.util.EncryptionUtils;
  8. import net.Bananas.BananaProxy.BananaProxy;
  9. import net.Bananas.BananaProxy.network.ProxyPlayerSession;
  10. import org.apache.http.HttpEntity;
  11. import org.apache.http.HttpHeaders;
  12. import org.apache.http.HttpResponse;
  13. import org.apache.http.NameValuePair;
  14. import org.apache.http.client.CookieStore;
  15. import org.apache.http.client.HttpClient;
  16. import org.apache.http.client.entity.UrlEncodedFormEntity;
  17. import org.apache.http.client.methods.HttpGet;
  18. import org.apache.http.client.methods.HttpPost;
  19. import org.apache.http.client.utils.URIBuilder;
  20. import org.apache.http.cookie.Cookie;
  21. import org.apache.http.entity.ContentType;
  22. import org.apache.http.entity.StringEntity;
  23. import org.apache.http.impl.client.BasicCookieStore;
  24. import org.apache.http.impl.client.HttpClientBuilder;
  25. import org.apache.http.message.BasicNameValuePair;
  26. import org.apache.http.protocol.HTTP;
  27. import org.apache.http.util.EntityUtils;
  28.  
  29. import java.io.IOException;
  30. import java.net.URI;
  31. import java.security.interfaces.ECPublicKey;
  32. import java.util.*;
  33. import java.util.concurrent.TimeUnit;
  34.  
  35. public class BedrockAuthentication {
  36.  
  37. private BedrockAuthentication() {}
  38.  
  39. public static final String XBOX_AUTH_URL = "https://login.live.com/oauth20_authorize.srf?client_id=00000000441cc96b&redirect_uri=https://login.live.com/oauth20_desktop.srf&response_type=token&display=touch&scope=service::user.auth.xboxlive.com::MBI_SSL&locale=en";
  40. public static final String XBOX_TOKEN_HOST = "login.live.com/oauth20_token.srf";
  41. public static final String XBOX_USER_AUTH_URL = "https://user.auth.xboxlive.com/user/authenticate";
  42. public static final String XBOX_AUTHORIZE_URL = "https://xsts.auth.xboxlive.com/xsts/authorize";
  43. public static final String BEDROCK_AUTH_URL = "https://multiplayer.minecraft.net/authentication";
  44.  
  45. public static String getChain(String login, String password) {
  46. try {
  47. LiveToken token = requestToken(login, password);
  48. XSTSToken xstsToken = requestXstsToken(token);
  49. return requestChain(xstsToken);
  50. } catch(Exception ex) {
  51. ex.printStackTrace();
  52. }
  53. return null;
  54. }
  55.  
  56. public static String requestChain(XSTSToken xstsToken) throws IOException {
  57. String publicKeyData = Base64.getEncoder().encodeToString(ProxyPlayerSession.PROXY_KEY_PAIR.getPublic().getEncoded());
  58. String data = "{\"identityPublicKey\":\"" + publicKeyData + "\"}";
  59.  
  60. HttpClient httpClient = HttpClientBuilder.create().build();
  61. HttpPost request = new HttpPost(BEDROCK_AUTH_URL);
  62. request.setEntity(new StringEntity(data, ContentType.APPLICATION_JSON));
  63. request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
  64. request.setHeader("Authorization", "XBL3.0 x=" + xstsToken.getUhs() + ";" + xstsToken.getToken());
  65. request.setHeader(HttpHeaders.USER_AGENT, "MCPE/UWP");
  66. request.setHeader("Client-Version", BananaProxy.BEDROCK_VERSION);
  67.  
  68. HttpResponse response = httpClient.execute(request);
  69. if(response.getStatusLine().getStatusCode() != 200) throw new IllegalStateException("bedrock authentication returned status code " + response.getStatusLine().getStatusCode());
  70. HttpEntity entity = response.getEntity();
  71. if(entity == null) throw new NullPointerException("entity is null");
  72. String responseStr = EntityUtils.toString(entity);
  73. if(responseStr == null) throw new NullPointerException("responseStr is null");
  74.  
  75. return responseStr;
  76. }
  77.  
  78. public static XSTSToken requestXstsToken(LiveToken token) throws IOException {
  79. HttpClient httpClient = HttpClientBuilder.create().build();
  80.  
  81. String userToken = requestUserToken(httpClient, token);
  82. if(userToken == null) throw new NullPointerException("userToken is null");
  83.  
  84. ObjectNode data = BananaProxy.JSON_MAPPER.createObjectNode();
  85. data.put("RelyingParty", "https://multiplayer.minecraft.net/");
  86. data.put("TokenType", "JWT");
  87. ObjectNode properties = BananaProxy.JSON_MAPPER.createObjectNode();
  88. properties.putArray("UserTokens").add(userToken);
  89. properties.put("SandboxId", "RETAIL");
  90. data.set("Properties", properties);
  91.  
  92. HttpPost request = new HttpPost(XBOX_AUTHORIZE_URL);
  93. request.setEntity(new StringEntity(data.toString(), ContentType.APPLICATION_JSON));
  94. request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
  95. request.setHeader("x-xbl-contract-version", "1");
  96.  
  97. HttpResponse response = httpClient.execute(request);
  98. if(response.getStatusLine().getStatusCode() != 200) throw new IllegalStateException("xsts authorization returned status code " + response.getStatusLine().getStatusCode());
  99. HttpEntity entity = response.getEntity();
  100. if(entity == null) throw new NullPointerException("entity is null");
  101. String responseStr = EntityUtils.toString(entity);
  102. if(responseStr == null) throw new NullPointerException("responseStr is null");
  103. JsonNode responseJson = BananaProxy.JSON_MAPPER.readTree(responseStr);
  104. return new XSTSToken(responseJson.get("Token").asText(), responseJson.get("DisplayClaims").get("xui").get(0).get("uhs").asText());
  105. }
  106.  
  107. public static String requestUserToken(HttpClient client, LiveToken liveToken) throws IOException {
  108. ObjectNode data = BananaProxy.JSON_MAPPER.createObjectNode();
  109. data.put("RelyingParty", "http://auth.xboxlive.com");
  110. data.put("TokenType", "JWT");
  111. ObjectNode dataProps = BananaProxy.JSON_MAPPER.createObjectNode();
  112. dataProps.put("AuthMethod", "RPS");
  113. dataProps.put("SiteName", "user.auth.xboxlive.com");
  114. dataProps.put("RpsTicket", "t=" + liveToken.getAccessToken());
  115. ObjectNode proofKey = BananaProxy.JSON_MAPPER.createObjectNode();
  116. proofKey.put("crv", "P-256");
  117. proofKey.put("alg", "ES256");
  118. proofKey.put("use", "sig");
  119. proofKey.put("kty", "EC");
  120. proofKey.put("x", Base64.getEncoder().encodeToString(((ECPublicKey) ProxyPlayerSession.PROXY_KEY_PAIR.getPublic()).getW().getAffineX().toByteArray()));
  121. proofKey.put("y", Base64.getEncoder().encodeToString(((ECPublicKey) ProxyPlayerSession.PROXY_KEY_PAIR.getPublic()).getW().getAffineY().toByteArray()));
  122. dataProps.set("ProofKey", proofKey);
  123. data.set("Properties", dataProps);
  124.  
  125. HttpPost request = new HttpPost(XBOX_USER_AUTH_URL);
  126. request.setEntity(new StringEntity(data.toString(), ContentType.APPLICATION_JSON));
  127. request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
  128. request.setHeader("x-xbl-contract-version", "1");
  129.  
  130. HttpResponse response = client.execute(request);
  131. if(response.getStatusLine().getStatusCode() != 200) throw new IllegalStateException("user token returned status code " + response.getStatusLine().getStatusCode());
  132. HttpEntity entity = response.getEntity();
  133. if(entity == null) throw new NullPointerException("entity is null");
  134. String responseStr = EntityUtils.toString(entity);
  135. if(responseStr == null) throw new NullPointerException("responseStr is null");
  136.  
  137. return BananaProxy.JSON_MAPPER.readTree(responseStr).get("Token").asText();
  138. }
  139.  
  140. public static LiveToken requestToken(String login, String password) throws Exception {
  141. CookieStore cookieStore = new BasicCookieStore();
  142. HttpClient httpClient = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).disableRedirectHandling().build();
  143. HttpGet authRequest = new HttpGet(XBOX_AUTH_URL);
  144. HttpResponse authResponse = httpClient.execute(authRequest);
  145. if(authResponse.getStatusLine().getStatusCode() != 200) throw new NullPointerException("xbox auth returned status code " + authResponse.getStatusLine().getStatusCode());
  146. HttpEntity authEntity = authResponse.getEntity();
  147. if(authEntity == null) throw new NullPointerException("authEntity is null");
  148. String authResponseString = EntityUtils.toString(authEntity);
  149.  
  150. String token = Util.getSFTTag(authResponseString);
  151. if(token == null) throw new IllegalStateException("sfttag not found in auth response");
  152. String credentialType = Util.getCredentialTypeEnd(authResponseString);
  153. if(credentialType == null) throw new IllegalStateException("credential type url not found in auth response");
  154. String urlPost = Util.getUrlPost(authResponseString);
  155. if(urlPost == null) throw new IllegalStateException("urlPost not found in auth response");
  156.  
  157. String uaid = null;
  158. for(Cookie cookie : cookieStore.getCookies()) {
  159. if(cookie.getName().equals("uaid")) uaid = cookie.getValue();
  160. }
  161. if(uaid == null) throw new NullPointerException("uaid is null");
  162.  
  163. ObjectNode jsonData = BananaProxy.JSON_MAPPER.createObjectNode();
  164. jsonData.put("username", login);
  165. jsonData.put("uaid", uaid);
  166. jsonData.put("isOtherIdpSupported", "false");
  167. jsonData.put("checkPhones", false);
  168. jsonData.put("isRemoteNGCSupported", true);
  169. jsonData.put("isCookieBannerShown", false);
  170. jsonData.put("isFidoSupported", false);
  171. jsonData.put("flowToken", token);
  172.  
  173. // idk what this request is for, but im leaving it cuz gophertunnel did it
  174. HttpPost credentialRequest = new HttpPost(credentialType);
  175. credentialRequest.setHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
  176. credentialRequest.setEntity(new StringEntity(jsonData.toString(), ContentType.APPLICATION_JSON));
  177. HttpResponse credentialResponse = httpClient.execute(credentialRequest);
  178. if(credentialResponse.getStatusLine().getStatusCode() != 200) throw new NullPointerException("credential type returned status code " + authResponse.getStatusLine().getStatusCode());
  179.  
  180. HttpPost urlPostRequest = new HttpPost(urlPost);
  181. urlPostRequest.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
  182.  
  183. List<NameValuePair> nvps = new ArrayList<>();
  184. nvps.add(new BasicNameValuePair("login", login));
  185. nvps.add(new BasicNameValuePair("passwd", password));
  186. nvps.add(new BasicNameValuePair("PPFT", token));
  187. nvps.add(new BasicNameValuePair("PPSX", "P"));
  188. nvps.add(new BasicNameValuePair("SI", "Sign in"));
  189. nvps.add(new BasicNameValuePair("type", "11"));
  190. nvps.add(new BasicNameValuePair("NewUser", "1"));
  191. nvps.add(new BasicNameValuePair("LoginOptions", "1"));
  192. urlPostRequest.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
  193.  
  194. HttpResponse urlPostResponse = httpClient.execute(urlPostRequest);
  195. int statusCode = urlPostResponse.getStatusLine().getStatusCode();
  196. if(statusCode != 200 && statusCode != 302) throw new NullPointerException("url post returned status code " + statusCode);
  197. HttpEntity urlPostEntity = urlPostResponse.getEntity();
  198. if(urlPostEntity == null) throw new NullPointerException("urlPostEntity is null");
  199. String urlPostResponseString = EntityUtils.toString(urlPostEntity);
  200. if(urlPostResponseString.equals("")) {
  201. String location = urlPostResponse.getFirstHeader("Location").getValue();
  202. if(location == null) throw new NullPointerException("location is null");
  203. Map<String, String> map = Util.getQueryMap("a://a?" + new URI(location).getFragment());
  204. String accessToken = map.get("access_token");
  205. String refreshToken = map.get("refresh_token");
  206. String expiryStr = map.get("expires_in");
  207. if(accessToken == null || refreshToken == null || expiryStr == null) throw new NullPointerException("could not get the token");
  208. return new LiveToken(accessToken, refreshToken, Integer.parseInt(expiryStr));
  209. } else {
  210. //invalid login info
  211. return null;
  212. }
  213. }
  214.  
  215. public static class XSTSToken {
  216. private String token;
  217. private String uhs;
  218.  
  219. public XSTSToken(String token, String uhs) {
  220. this.token = token;
  221. this.uhs = uhs;
  222. }
  223.  
  224. public String getToken() {
  225. return token;
  226. }
  227.  
  228. public String getUhs() {
  229. return uhs;
  230. }
  231. }
  232.  
  233. public static class LiveToken {
  234. private String accessToken, refreshToken;
  235. private long expiry;
  236.  
  237. private LiveToken(String accessToken, String refreshToken, int expiry) {
  238. this.accessToken = accessToken;
  239. this.refreshToken = refreshToken;
  240. this.expiry = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expiry);
  241. }
  242.  
  243. public String getAccessToken() {
  244. update();
  245. return accessToken;
  246. }
  247.  
  248. public String getRefreshToken() {
  249. update();
  250. return refreshToken;
  251. }
  252.  
  253. public long getExpiry() {
  254. update();
  255. return expiry;
  256. }
  257.  
  258. public boolean isExpired() {
  259. return expiry <= System.currentTimeMillis();
  260. }
  261.  
  262. public void update() {
  263. if(isExpired()) refresh();
  264. }
  265.  
  266. private boolean refresh() {
  267. try {
  268. List<NameValuePair> params = new ArrayList<>();
  269. params.add(new BasicNameValuePair("grant_type", "refresh_token"));
  270. params.add(new BasicNameValuePair("client_id", "00000000441cc96b"));
  271. params.add(new BasicNameValuePair("scope", "service::user.auth.xboxlive.com::MBI_SSL"));
  272. params.add(new BasicNameValuePair("refresh_token", refreshToken));
  273.  
  274. String url;
  275. url = new URIBuilder().setScheme("https").setHost(XBOX_TOKEN_HOST).setParameters(params).build().toASCIIString();
  276. if(url == null) throw new NullPointerException("url is null");
  277.  
  278. HttpClient client = HttpClientBuilder.create().build();
  279. HttpGet refresh = new HttpGet(url);
  280. HttpResponse response = client.execute(refresh);
  281. if(response.getStatusLine().getStatusCode() != 200) throw new IllegalStateException("token refresh returned status code " + response.getStatusLine().getStatusCode());
  282. HttpEntity entity = response.getEntity();
  283. if(entity == null) throw new NullPointerException("entity is null");
  284. String responseStr = EntityUtils.toString(entity);
  285. if(responseStr == null) throw new NullPointerException("responseStr is null");
  286. JsonNode json = BananaProxy.JSON_MAPPER.readTree(responseStr);
  287. accessToken = json.get("access_token").asText();
  288. refreshToken = json.get("refresh_token").asText();
  289. expiry = json.get("expires_in").asInt();
  290. return true;
  291. } catch(Exception ex) {
  292. ex.printStackTrace();
  293. return false;
  294. }
  295. }
  296. }
  297.  
  298. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement