package io.gitlab.jfronny.inceptum.windows; import imgui.ImGui; import io.gitlab.jfronny.inceptum.Inceptum; import io.gitlab.jfronny.inceptum.model.microsoft.*; import io.gitlab.jfronny.inceptum.util.account.AccountManager; import io.gitlab.jfronny.inceptum.util.account.MicrosoftAccount; import io.gitlab.jfronny.inceptum.util.account.MicrosoftAuthAPI; import io.gitlab.jfronny.inceptum.util.Utils; import net.freeutils.httpserver.HTTPServer; import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; public class MicrosoftLoginWindow extends Window { private static HTTPServer server = new HTTPServer(28562); private static HTTPServer.VirtualHost host = server.getVirtualHost(null); private static final String MICROSOFT_LOGIN_URL = "https://login.live.com/oauth20_authorize.srf?client_id=90890812-00d1-48a8-8d3f-38465ef43b58&prompt=select_account&cobrandid=8058f65d-ce06-4c30-9559-473c9275a65d&response_type=code&scope=XboxLive.signin%20XboxLive.offline_access&redirect_uri=http%3A%2F%2F127.0.0.1%3A28562"; private MicrosoftAccount account; public MicrosoftLoginWindow() { this(null); } public MicrosoftLoginWindow(MicrosoftAccount account) { super("Microsoft Login"); this.account = account; try { startServer(); } catch (Exception e) { Inceptum.LOGGER.error("Could not start mc login server", e); } } @Override public void draw() { ImGui.text("This feature uses modified ATLauncher code"); ImGui.text("Click the button below to begin"); if (ImGui.button("Open in Browser")) { try { Utils.openWebBrowser(new URI(MICROSOFT_LOGIN_URL)); } catch (URISyntaxException e) { Inceptum.LOGGER.error("Could not open browser", e); } } } private void startServer() throws Exception { host.addContext("/", (req, res) -> { if (req.getParams().containsKey("error")) { res.getHeaders().add("Content-Type", "text/plain"); res.send(500, "Error logging in. Check console for more information"); Inceptum.LOGGER.error("Error logging into Microsoft account: " + URLDecoder .decode(req.getParams().get("error_description"), StandardCharsets.UTF_8.toString())); close(); return 0; } if (!req.getParams().containsKey("code")) { res.getHeaders().add("Content-Type", "text/plain"); res.send(400, "Code is missing"); close(); return 0; } try { acquireAccessToken(req.getParams().get("code")); } catch (Exception e) { Inceptum.LOGGER.error("Error acquiring accessToken", e); res.getHeaders().add("Content-Type", "text/html"); res.send(500, "Error logging in. Check console for more information"); close(); return 0; } res.getHeaders().add("Content-Type", "text/plain"); // #. {0} is the name of the launcher res.send(200, "Login complete. You can now close this window and go back to GLaunch"); close(); return 0; }, "GET"); server.start(); } private void acquireAccessToken(String authcode) throws Exception { OauthTokenResponse oauthTokenResponse = MicrosoftAuthAPI.tradeCodeForAccessToken(authcode); acquireXBLToken(oauthTokenResponse); } private void acquireXBLToken(OauthTokenResponse oauthTokenResponse) throws Exception { XboxLiveAuthResponse xblAuthResponse = MicrosoftAuthAPI.getXBLToken(oauthTokenResponse.accessToken); acquireXsts(oauthTokenResponse, xblAuthResponse.token); } private void acquireXsts(OauthTokenResponse oauthTokenResponse, String xblToken) throws Exception { XboxLiveAuthResponse xstsAuthResponse = null; xstsAuthResponse = MicrosoftAuthAPI.getXstsToken(xblToken); /*try { xstsAuthResponse = MicrosoftAuthAPI.getXstsToken(xblToken); } catch (DownloadException e) { if (e.response != null) { GLaunch.LOGGER.debug(Gsons.DEFAULT.toJson(e.response)); XboxLiveAuthErrorResponse xboxLiveAuthErrorResponse = Gsons.DEFAULT.fromJson(e.response, XboxLiveAuthErrorResponse.class); String error = xboxLiveAuthErrorResponse.getErrorMessageForCode(); if (error != null) { GLaunch.LOGGER.warn(error); DialogManager.okDialog().setTitle("Error logging into Xbox Live") .setContent(new HTMLBuilder().center().text(error).build()).setType(DialogManager.ERROR) .show(); String link = xboxLiveAuthErrorResponse.getBrowserLinkForCode(); if (link != null) { Utils.openWebBrowser(new URI(link)); } } throw e; } }*/ if (xstsAuthResponse != null) { acquireMinecraftToken(oauthTokenResponse, xstsAuthResponse); } } private void acquireMinecraftToken(OauthTokenResponse oauthTokenResponse, XboxLiveAuthResponse xstsAuthResponse) throws Exception { String xblUhs = xstsAuthResponse.displayClaims.xui.get(0).uhs; String xblXsts = xstsAuthResponse.token; LoginResponse loginResponse = MicrosoftAuthAPI.loginToMinecraft("XBL3.0 x=" + xblUhs + ";" + xblXsts); Store store = MicrosoftAuthAPI.getMcEntitlements(loginResponse.accessToken); Inceptum.LOGGER.info(Inceptum.GSON.toJson(store)); if (!(store.items.stream().anyMatch(i -> i.name.equalsIgnoreCase("product_minecraft")) && store.items.stream().anyMatch(i -> i.name.equalsIgnoreCase("game_minecraft")))) { Inceptum.open(new AlertWindow("This account doesn't have a valid purchase of Minecraft.\nPlease make sure you've bought the Java edition of Minecraft and then try again.")); throw new Exception("Account does not own Minecraft"); } Profile profile = MicrosoftAuthAPI.getMcProfile(loginResponse.accessToken); if (profile == null) { throw new Exception("Failed to get Minecraft profile"); } // add the account addAccount(oauthTokenResponse, xstsAuthResponse, loginResponse, profile); } private void addAccount(OauthTokenResponse oauthTokenResponse, XboxLiveAuthResponse xstsAuthResponse, LoginResponse loginResponse, Profile profile) throws Exception { if (account != null || AccountManager.isAccountByName(loginResponse.username)) { MicrosoftAccount account = (MicrosoftAccount) AccountManager.getAccountByName(loginResponse.username); if (account == null) { return; } // if forced to relogin, then make sure they logged into correct account if (account != null && this.account != null && account.accountId != this.account.accountId) { Inceptum.open(new AlertWindow("Logged into incorrect account. Please login again on the Accounts tab")); return; } account.update(oauthTokenResponse, xstsAuthResponse, loginResponse, profile); AccountManager.saveAccounts(); } else { MicrosoftAccount account = new MicrosoftAccount(oauthTokenResponse, xstsAuthResponse, loginResponse, profile); AccountManager.addAccount(account); } } }