213 lines
7.1 KiB
Java
213 lines
7.1 KiB
Java
package io.gitlab.jfronny.inceptum.launcher.api.account;
|
|
|
|
import io.gitlab.jfronny.commons.ref.R;
|
|
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
|
import io.gitlab.jfronny.inceptum.common.GsonPreset;
|
|
import io.gitlab.jfronny.inceptum.common.Utils;
|
|
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
|
import io.gitlab.jfronny.inceptum.launcher.gson.MicrosoftAccountAdapter;
|
|
import io.gitlab.jfronny.inceptum.launcher.gson.MicrosoftAccountMeta;
|
|
import io.gitlab.jfronny.inceptum.launcher.model.microsoft.Profile;
|
|
import io.gitlab.jfronny.inceptum.launcher.model.microsoft.response.*;
|
|
|
|
import java.io.IOException;
|
|
import java.net.URISyntaxException;
|
|
import java.util.*;
|
|
|
|
@GSerializable(with = MicrosoftAccountAdapter.class, configure = GsonPreset.Config.class)
|
|
public class MicrosoftAccount {
|
|
/**
|
|
* The username/email/id of the account.
|
|
*/
|
|
public String accountId;
|
|
|
|
/**
|
|
* The account's Minecraft username.
|
|
*/
|
|
public String minecraftUsername;
|
|
|
|
/**
|
|
* The UUID of the account.
|
|
*/
|
|
public String uuid;
|
|
|
|
/**
|
|
* The access token.
|
|
*/
|
|
public String accessToken;
|
|
|
|
/**
|
|
* The Microsoft oauth token.
|
|
*/
|
|
public OauthTokenResponse oauthToken;
|
|
|
|
/**
|
|
* The xsts auth response.
|
|
*/
|
|
public XboxLiveAuthResponse xstsAuth;
|
|
|
|
/**
|
|
* The date that the accessToken expires at.
|
|
*/
|
|
public Date accessTokenExpiresAt;
|
|
|
|
/**
|
|
* If the user must login again. This is usually the result of a failed
|
|
* accessToken refresh.
|
|
*/
|
|
public boolean mustLogin;
|
|
|
|
public MicrosoftAccount(MicrosoftAccountMeta meta) {
|
|
this.accountId = meta.accountId();
|
|
this.minecraftUsername = meta.minecraftUsername();
|
|
this.uuid = meta.uuid();
|
|
this.accessToken = meta.accessToken();
|
|
this.oauthToken = meta.oauthToken();
|
|
this.xstsAuth = meta.xstsAuth();
|
|
this.accessTokenExpiresAt = meta.accessTokenExpiresAt();
|
|
this.mustLogin = meta.mustLogin();
|
|
}
|
|
|
|
public MicrosoftAccountMeta toMeta() {
|
|
return new MicrosoftAccountMeta(
|
|
accountId,
|
|
minecraftUsername,
|
|
uuid,
|
|
accessToken,
|
|
oauthToken,
|
|
xstsAuth,
|
|
accessTokenExpiresAt,
|
|
mustLogin
|
|
);
|
|
}
|
|
|
|
public MicrosoftAccount(OauthTokenResponse oauthTokenResponse, XboxLiveAuthResponse xstsAuthResponse,
|
|
LoginResponse loginResponse, Profile profile) {
|
|
update(oauthTokenResponse, xstsAuthResponse, loginResponse, profile);
|
|
}
|
|
|
|
public void update(OauthTokenResponse oauthTokenResponse, XboxLiveAuthResponse xstsAuthResponse,
|
|
LoginResponse loginResponse, Profile profile) {
|
|
this.oauthToken = oauthTokenResponse;
|
|
this.xstsAuth = xstsAuthResponse;
|
|
this.accessToken = loginResponse.accessToken();
|
|
this.minecraftUsername = profile.name();
|
|
this.uuid = profile.id();
|
|
this.accountId = loginResponse.username();
|
|
this.mustLogin = false;
|
|
|
|
this.accessTokenExpiresAt = new Date();
|
|
this.accessTokenExpiresAt.setTime(this.accessTokenExpiresAt.getTime() + loginResponse.expiresIn() * 1000);
|
|
}
|
|
|
|
public String getAccessToken() {
|
|
return accessToken;
|
|
}
|
|
|
|
public String getSessionToken() {
|
|
return accessToken;
|
|
}
|
|
|
|
public String getCurrentUsername() throws IOException, URISyntaxException {
|
|
Profile profile = MicrosoftAuthAPI.getMcProfile(accessToken);
|
|
if (profile.name() == null) throw new IOException("Got null name");
|
|
return profile.name();
|
|
}
|
|
|
|
public void updateSkinPreCheck() {
|
|
this.refreshAccessToken();
|
|
}
|
|
|
|
public String getSkinUrl() throws IOException, URISyntaxException {
|
|
Profile profile = MicrosoftAuthAPI.getMcProfile(accessToken);
|
|
return Optional.of(profile.skins()).orElse(new ArrayList<>())
|
|
.stream()
|
|
.filter(s -> s.state().equalsIgnoreCase("ACTIVE"))
|
|
.findFirst()
|
|
.map(Profile.Skin::url)
|
|
.orElse(null);
|
|
}
|
|
|
|
public boolean refreshAccessToken() {
|
|
return refreshAccessToken(false);
|
|
}
|
|
|
|
public boolean refreshAccessToken(boolean force) {
|
|
try {
|
|
if (force || new Date().after(this.oauthToken.expiresAt())) {
|
|
Utils.LOGGER.info("Oauth token expired. Attempting to refresh");
|
|
OauthTokenResponse oauthTokenResponse = MicrosoftAuthAPI.refreshAccessToken(oauthToken.refreshToken());
|
|
|
|
if (oauthTokenResponse == null) {
|
|
mustLogin = true;
|
|
AccountManager.saveAccounts();
|
|
Utils.LOGGER.error("Failed to refresh accessToken");
|
|
return false;
|
|
}
|
|
|
|
this.oauthToken = oauthTokenResponse;
|
|
|
|
AccountManager.saveAccounts();
|
|
}
|
|
|
|
if (force || new Date().after(this.xstsAuth.notAfter())) {
|
|
Utils.LOGGER.info("xsts auth expired. Attempting to get new auth");
|
|
XboxLiveAuthResponse xboxLiveAuthResponse = MicrosoftAuthAPI.getXBLToken(this.oauthToken.accessToken());
|
|
this.xstsAuth = MicrosoftAuthAPI.getXstsToken(xboxLiveAuthResponse.token());
|
|
|
|
if (xstsAuth == null) {
|
|
mustLogin = true;
|
|
AccountManager.saveAccounts();
|
|
Utils.LOGGER.error("Failed to get XBLToken");
|
|
return false;
|
|
}
|
|
|
|
AccountManager.saveAccounts();
|
|
}
|
|
|
|
if (force || new Date().after(this.accessTokenExpiresAt)) {
|
|
LoginResponse loginResponse = MicrosoftAuthAPI.loginToMinecraft(getIdentityToken());
|
|
|
|
if (loginResponse == null) {
|
|
mustLogin = true;
|
|
AccountManager.saveAccounts();
|
|
Utils.LOGGER.error("Failed to login to Minecraft");
|
|
return false;
|
|
}
|
|
|
|
this.accessToken = loginResponse.accessToken();
|
|
this.accountId = loginResponse.username();
|
|
|
|
this.accessTokenExpiresAt = new Date();
|
|
this.accessTokenExpiresAt.setTime(this.accessTokenExpiresAt.getTime() + loginResponse.expiresIn() * 1000);
|
|
|
|
AccountManager.saveAccounts();
|
|
}
|
|
} catch (Exception e) {
|
|
mustLogin = true;
|
|
AccountManager.saveAccounts();
|
|
|
|
Utils.LOGGER.error("Exception refreshing accessToken", e);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private String getIdentityToken() {
|
|
return "XBL3.0 x=" + xstsAuth.displayClaims().xui().get(0).uhs() + ";" + xstsAuth.token();
|
|
}
|
|
|
|
public boolean ensureAccessTokenValid() {
|
|
if (mustLogin) {
|
|
LauncherEnv.showOkCancel("You must login again in order to continue", "Login expired", () -> LauncherEnv.showLoginRefreshPrompt(this), R::nop);
|
|
return false;
|
|
} else return true;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return minecraftUsername;
|
|
}
|
|
}
|