Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package net.VytskaLT.BananaProxy.network.auth;
- import com.fasterxml.jackson.core.type.TypeReference;
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.node.ArrayNode;
- import com.fasterxml.jackson.databind.node.ObjectNode;
- import com.nukkitx.protocol.bedrock.util.EncryptionUtils;
- import net.Bananas.BananaProxy.BananaProxy;
- import net.Bananas.BananaProxy.network.ProxyPlayerSession;
- import org.apache.http.HttpEntity;
- import org.apache.http.HttpHeaders;
- import org.apache.http.HttpResponse;
- import org.apache.http.NameValuePair;
- import org.apache.http.client.CookieStore;
- import org.apache.http.client.HttpClient;
- import org.apache.http.client.entity.UrlEncodedFormEntity;
- import org.apache.http.client.methods.HttpGet;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.client.utils.URIBuilder;
- import org.apache.http.cookie.Cookie;
- import org.apache.http.entity.ContentType;
- import org.apache.http.entity.StringEntity;
- import org.apache.http.impl.client.BasicCookieStore;
- import org.apache.http.impl.client.HttpClientBuilder;
- import org.apache.http.message.BasicNameValuePair;
- import org.apache.http.protocol.HTTP;
- import org.apache.http.util.EntityUtils;
- import java.io.IOException;
- import java.net.URI;
- import java.security.interfaces.ECPublicKey;
- import java.util.*;
- import java.util.concurrent.TimeUnit;
- public class BedrockAuthentication {
- private BedrockAuthentication() {}
- 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";
- public static final String XBOX_TOKEN_HOST = "login.live.com/oauth20_token.srf";
- public static final String XBOX_USER_AUTH_URL = "https://user.auth.xboxlive.com/user/authenticate";
- public static final String XBOX_AUTHORIZE_URL = "https://xsts.auth.xboxlive.com/xsts/authorize";
- public static final String BEDROCK_AUTH_URL = "https://multiplayer.minecraft.net/authentication";
- public static String getChain(String login, String password) {
- try {
- LiveToken token = requestToken(login, password);
- XSTSToken xstsToken = requestXstsToken(token);
- return requestChain(xstsToken);
- } catch(Exception ex) {
- ex.printStackTrace();
- }
- return null;
- }
- public static String requestChain(XSTSToken xstsToken) throws IOException {
- String publicKeyData = Base64.getEncoder().encodeToString(ProxyPlayerSession.PROXY_KEY_PAIR.getPublic().getEncoded());
- String data = "{\"identityPublicKey\":\"" + publicKeyData + "\"}";
- HttpClient httpClient = HttpClientBuilder.create().build();
- HttpPost request = new HttpPost(BEDROCK_AUTH_URL);
- request.setEntity(new StringEntity(data, ContentType.APPLICATION_JSON));
- request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
- request.setHeader("Authorization", "XBL3.0 x=" + xstsToken.getUhs() + ";" + xstsToken.getToken());
- request.setHeader(HttpHeaders.USER_AGENT, "MCPE/UWP");
- request.setHeader("Client-Version", BananaProxy.BEDROCK_VERSION);
- HttpResponse response = httpClient.execute(request);
- if(response.getStatusLine().getStatusCode() != 200) throw new IllegalStateException("bedrock authentication returned status code " + response.getStatusLine().getStatusCode());
- HttpEntity entity = response.getEntity();
- if(entity == null) throw new NullPointerException("entity is null");
- String responseStr = EntityUtils.toString(entity);
- if(responseStr == null) throw new NullPointerException("responseStr is null");
- return responseStr;
- }
- public static XSTSToken requestXstsToken(LiveToken token) throws IOException {
- HttpClient httpClient = HttpClientBuilder.create().build();
- String userToken = requestUserToken(httpClient, token);
- if(userToken == null) throw new NullPointerException("userToken is null");
- ObjectNode data = BananaProxy.JSON_MAPPER.createObjectNode();
- data.put("RelyingParty", "https://multiplayer.minecraft.net/");
- data.put("TokenType", "JWT");
- ObjectNode properties = BananaProxy.JSON_MAPPER.createObjectNode();
- properties.putArray("UserTokens").add(userToken);
- properties.put("SandboxId", "RETAIL");
- data.set("Properties", properties);
- HttpPost request = new HttpPost(XBOX_AUTHORIZE_URL);
- request.setEntity(new StringEntity(data.toString(), ContentType.APPLICATION_JSON));
- request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
- request.setHeader("x-xbl-contract-version", "1");
- HttpResponse response = httpClient.execute(request);
- if(response.getStatusLine().getStatusCode() != 200) throw new IllegalStateException("xsts authorization returned status code " + response.getStatusLine().getStatusCode());
- HttpEntity entity = response.getEntity();
- if(entity == null) throw new NullPointerException("entity is null");
- String responseStr = EntityUtils.toString(entity);
- if(responseStr == null) throw new NullPointerException("responseStr is null");
- JsonNode responseJson = BananaProxy.JSON_MAPPER.readTree(responseStr);
- return new XSTSToken(responseJson.get("Token").asText(), responseJson.get("DisplayClaims").get("xui").get(0).get("uhs").asText());
- }
- public static String requestUserToken(HttpClient client, LiveToken liveToken) throws IOException {
- ObjectNode data = BananaProxy.JSON_MAPPER.createObjectNode();
- data.put("RelyingParty", "http://auth.xboxlive.com");
- data.put("TokenType", "JWT");
- ObjectNode dataProps = BananaProxy.JSON_MAPPER.createObjectNode();
- dataProps.put("AuthMethod", "RPS");
- dataProps.put("SiteName", "user.auth.xboxlive.com");
- dataProps.put("RpsTicket", "t=" + liveToken.getAccessToken());
- ObjectNode proofKey = BananaProxy.JSON_MAPPER.createObjectNode();
- proofKey.put("crv", "P-256");
- proofKey.put("alg", "ES256");
- proofKey.put("use", "sig");
- proofKey.put("kty", "EC");
- proofKey.put("x", Base64.getEncoder().encodeToString(((ECPublicKey) ProxyPlayerSession.PROXY_KEY_PAIR.getPublic()).getW().getAffineX().toByteArray()));
- proofKey.put("y", Base64.getEncoder().encodeToString(((ECPublicKey) ProxyPlayerSession.PROXY_KEY_PAIR.getPublic()).getW().getAffineY().toByteArray()));
- dataProps.set("ProofKey", proofKey);
- data.set("Properties", dataProps);
- HttpPost request = new HttpPost(XBOX_USER_AUTH_URL);
- request.setEntity(new StringEntity(data.toString(), ContentType.APPLICATION_JSON));
- request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
- request.setHeader("x-xbl-contract-version", "1");
- HttpResponse response = client.execute(request);
- if(response.getStatusLine().getStatusCode() != 200) throw new IllegalStateException("user token returned status code " + response.getStatusLine().getStatusCode());
- HttpEntity entity = response.getEntity();
- if(entity == null) throw new NullPointerException("entity is null");
- String responseStr = EntityUtils.toString(entity);
- if(responseStr == null) throw new NullPointerException("responseStr is null");
- return BananaProxy.JSON_MAPPER.readTree(responseStr).get("Token").asText();
- }
- public static LiveToken requestToken(String login, String password) throws Exception {
- CookieStore cookieStore = new BasicCookieStore();
- HttpClient httpClient = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).disableRedirectHandling().build();
- HttpGet authRequest = new HttpGet(XBOX_AUTH_URL);
- HttpResponse authResponse = httpClient.execute(authRequest);
- if(authResponse.getStatusLine().getStatusCode() != 200) throw new NullPointerException("xbox auth returned status code " + authResponse.getStatusLine().getStatusCode());
- HttpEntity authEntity = authResponse.getEntity();
- if(authEntity == null) throw new NullPointerException("authEntity is null");
- String authResponseString = EntityUtils.toString(authEntity);
- String token = Util.getSFTTag(authResponseString);
- if(token == null) throw new IllegalStateException("sfttag not found in auth response");
- String credentialType = Util.getCredentialTypeEnd(authResponseString);
- if(credentialType == null) throw new IllegalStateException("credential type url not found in auth response");
- String urlPost = Util.getUrlPost(authResponseString);
- if(urlPost == null) throw new IllegalStateException("urlPost not found in auth response");
- String uaid = null;
- for(Cookie cookie : cookieStore.getCookies()) {
- if(cookie.getName().equals("uaid")) uaid = cookie.getValue();
- }
- if(uaid == null) throw new NullPointerException("uaid is null");
- ObjectNode jsonData = BananaProxy.JSON_MAPPER.createObjectNode();
- jsonData.put("username", login);
- jsonData.put("uaid", uaid);
- jsonData.put("isOtherIdpSupported", "false");
- jsonData.put("checkPhones", false);
- jsonData.put("isRemoteNGCSupported", true);
- jsonData.put("isCookieBannerShown", false);
- jsonData.put("isFidoSupported", false);
- jsonData.put("flowToken", token);
- // idk what this request is for, but im leaving it cuz gophertunnel did it
- HttpPost credentialRequest = new HttpPost(credentialType);
- credentialRequest.setHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
- credentialRequest.setEntity(new StringEntity(jsonData.toString(), ContentType.APPLICATION_JSON));
- HttpResponse credentialResponse = httpClient.execute(credentialRequest);
- if(credentialResponse.getStatusLine().getStatusCode() != 200) throw new NullPointerException("credential type returned status code " + authResponse.getStatusLine().getStatusCode());
- HttpPost urlPostRequest = new HttpPost(urlPost);
- urlPostRequest.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
- List<NameValuePair> nvps = new ArrayList<>();
- nvps.add(new BasicNameValuePair("login", login));
- nvps.add(new BasicNameValuePair("passwd", password));
- nvps.add(new BasicNameValuePair("PPFT", token));
- nvps.add(new BasicNameValuePair("PPSX", "P"));
- nvps.add(new BasicNameValuePair("SI", "Sign in"));
- nvps.add(new BasicNameValuePair("type", "11"));
- nvps.add(new BasicNameValuePair("NewUser", "1"));
- nvps.add(new BasicNameValuePair("LoginOptions", "1"));
- urlPostRequest.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
- HttpResponse urlPostResponse = httpClient.execute(urlPostRequest);
- int statusCode = urlPostResponse.getStatusLine().getStatusCode();
- if(statusCode != 200 && statusCode != 302) throw new NullPointerException("url post returned status code " + statusCode);
- HttpEntity urlPostEntity = urlPostResponse.getEntity();
- if(urlPostEntity == null) throw new NullPointerException("urlPostEntity is null");
- String urlPostResponseString = EntityUtils.toString(urlPostEntity);
- if(urlPostResponseString.equals("")) {
- String location = urlPostResponse.getFirstHeader("Location").getValue();
- if(location == null) throw new NullPointerException("location is null");
- Map<String, String> map = Util.getQueryMap("a://a?" + new URI(location).getFragment());
- String accessToken = map.get("access_token");
- String refreshToken = map.get("refresh_token");
- String expiryStr = map.get("expires_in");
- if(accessToken == null || refreshToken == null || expiryStr == null) throw new NullPointerException("could not get the token");
- return new LiveToken(accessToken, refreshToken, Integer.parseInt(expiryStr));
- } else {
- //invalid login info
- return null;
- }
- }
- public static class XSTSToken {
- private String token;
- private String uhs;
- public XSTSToken(String token, String uhs) {
- this.token = token;
- this.uhs = uhs;
- }
- public String getToken() {
- return token;
- }
- public String getUhs() {
- return uhs;
- }
- }
- public static class LiveToken {
- private String accessToken, refreshToken;
- private long expiry;
- private LiveToken(String accessToken, String refreshToken, int expiry) {
- this.accessToken = accessToken;
- this.refreshToken = refreshToken;
- this.expiry = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expiry);
- }
- public String getAccessToken() {
- update();
- return accessToken;
- }
- public String getRefreshToken() {
- update();
- return refreshToken;
- }
- public long getExpiry() {
- update();
- return expiry;
- }
- public boolean isExpired() {
- return expiry <= System.currentTimeMillis();
- }
- public void update() {
- if(isExpired()) refresh();
- }
- private boolean refresh() {
- try {
- List<NameValuePair> params = new ArrayList<>();
- params.add(new BasicNameValuePair("grant_type", "refresh_token"));
- params.add(new BasicNameValuePair("client_id", "00000000441cc96b"));
- params.add(new BasicNameValuePair("scope", "service::user.auth.xboxlive.com::MBI_SSL"));
- params.add(new BasicNameValuePair("refresh_token", refreshToken));
- String url;
- url = new URIBuilder().setScheme("https").setHost(XBOX_TOKEN_HOST).setParameters(params).build().toASCIIString();
- if(url == null) throw new NullPointerException("url is null");
- HttpClient client = HttpClientBuilder.create().build();
- HttpGet refresh = new HttpGet(url);
- HttpResponse response = client.execute(refresh);
- if(response.getStatusLine().getStatusCode() != 200) throw new IllegalStateException("token refresh returned status code " + response.getStatusLine().getStatusCode());
- HttpEntity entity = response.getEntity();
- if(entity == null) throw new NullPointerException("entity is null");
- String responseStr = EntityUtils.toString(entity);
- if(responseStr == null) throw new NullPointerException("responseStr is null");
- JsonNode json = BananaProxy.JSON_MAPPER.readTree(responseStr);
- accessToken = json.get("access_token").asText();
- refreshToken = json.get("refresh_token").asText();
- expiry = json.get("expires_in").asInt();
- return true;
- } catch(Exception ex) {
- ex.printStackTrace();
- return false;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement