Inceptum/src/main/java/io/gitlab/jfronny/inceptum/util/account/MicrosoftAccount.java

221 lines
7.0 KiB
Java

package io.gitlab.jfronny.inceptum.util.account;
import io.gitlab.jfronny.inceptum.Inceptum;
import io.gitlab.jfronny.inceptum.model.microsoft.LoginResponse;
import io.gitlab.jfronny.inceptum.model.microsoft.OauthTokenResponse;
import io.gitlab.jfronny.inceptum.model.microsoft.Profile;
import io.gitlab.jfronny.inceptum.model.microsoft.XboxLiveAuthResponse;
import io.gitlab.jfronny.inceptum.windows.AlertWindow;
import io.gitlab.jfronny.inceptum.windows.MicrosoftLoginWindow;
import java.util.ArrayList;
import java.util.Date;
import java.util.Optional;
import java.util.function.Consumer;
public class MicrosoftAccount {
/**
* Auto generated serial.
*/
private static final long serialVersionUID = 5483749902584257559L;
/**
* 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(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() {
Profile profile = MicrosoftAuthAPI.getMcProfile(accessToken);
if (profile == null) {
Inceptum.LOGGER.error("Error getting Minecraft profile");
return null;
}
return Optional.of(profile.name).orElse(null);
}
public void updateSkinPreCheck() {
this.refreshAccessToken();
}
public String getSkinUrl() {
Profile profile = MicrosoftAuthAPI.getMcProfile(accessToken);
if (profile == null) {
Inceptum.LOGGER.error("Error getting Minecraft profile");
return null;
}
return Optional.of(profile.skins).orElse(new ArrayList<>()).stream()
.filter(s -> s.state.equalsIgnoreCase("ACTIVE")).findFirst().map(s -> s.url).orElse(null);
}
public boolean refreshAccessToken() {
return refreshAccessToken(false);
}
public boolean refreshAccessToken(boolean force) {
try {
if (force || new Date().after(this.oauthToken.expiresAt)) {
Inceptum.LOGGER.info("Oauth token expired. Attempting to refresh");
OauthTokenResponse oauthTokenResponse = MicrosoftAuthAPI.refreshAccessToken(oauthToken.refreshToken);
if (oauthTokenResponse == null) {
mustLogin = true;
AccountManager.saveAccounts();
Inceptum.LOGGER.error("Failed to refresh accessToken");
return false;
}
this.oauthToken = oauthTokenResponse;
AccountManager.saveAccounts();
}
if (force || new Date().after(this.xstsAuth.notAfter)) {
Inceptum.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();
Inceptum.LOGGER.error("Failed to get XBLToken");
return false;
}
AccountManager.saveAccounts();
}
if (force || new Date().after(this.accessTokenExpiresAt)) {
LoginResponse loginResponse = MicrosoftAuthAPI.loginToMinecraft(this.getIdentityToken());
if (loginResponse == null) {
mustLogin = true;
AccountManager.saveAccounts();
Inceptum.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();
Inceptum.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 void ensureAccessTokenValid(Consumer<Boolean> isValid) {
boolean hasCancelled = false;
if (mustLogin) {
Inceptum.open(new AlertWindow("You must login again in order to continue", () -> {
Inceptum.open(new MicrosoftLoginWindow(this));
if (!new Date().after(accessTokenExpiresAt)) {
isValid.accept(true);
return;
}
Inceptum.LOGGER.info("Access Token has expired. Attempting to refresh it.");
try {
isValid.accept(refreshAccessToken());
return;
} catch (Exception e) {
Inceptum.LOGGER.error("Exception while attempting to refresh access token", e);
}
isValid.accept(false);
}, () -> {
isValid.accept(false);
}));
}
}
@Override
public String toString() {
return minecraftUsername;
}
}