fix: process microsoft account login error code.

This commit is contained in:
huanghongxun 2021-08-28 19:37:51 +08:00
parent b9382ce966
commit dc32151501
4 changed files with 58 additions and 1 deletions

View File

@ -37,6 +37,7 @@ import javafx.scene.layout.*;
import org.jackhuang.hmcl.auth.*;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.auth.microsoft.MicrosoftService;
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
import org.jackhuang.hmcl.auth.yggdrasil.RemoteAuthenticationException;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService;
@ -385,6 +386,15 @@ public class AddAccountPane extends StackPane {
return i18n("account.failed.character_deleted");
} else if (exception instanceof InvalidSkinException) {
return i18n("account.skin.invalid_skin");
} else if (exception instanceof MicrosoftService.XboxAuthorizationException) {
long errorCode = ((MicrosoftService.XboxAuthorizationException) exception).getErrorCode();
if (errorCode == MicrosoftService.XboxAuthorizationException.ADD_FAMILY) {
return i18n("account.methods.microsoft.error.add_family");
} else if (errorCode == MicrosoftService.XboxAuthorizationException.MISSING_XBOX_ACCOUNT) {
return i18n("account.methods.microsoft.error.missing_xbox_account");
} else {
return i18n("account.methods.microsoft.error.unknown", errorCode);
}
} else if (exception.getClass() == AuthenticationException.class) {
return exception.getLocalizedMessage();
} else {

View File

@ -66,6 +66,9 @@ account.methods=Login Type
account.methods.authlib_injector=authlib-injector
account.methods.microsoft=Microsoft Account
account.methods.microsoft.close_page=Microsoft account authorization has been finished. There are some remaining logging-in steps to be finished later. You can close this page right now.
account.methods.microsoft.error.add_family=Since you are not yet 18 years old, an adult must add you to a family in order for you to play Minecraft.
account.methods.microsoft.error.missing_xbox_account=Your Microsoft account is not connected to an Xbox account. Please create one before continuing.
account.methods.microsoft.error.unknown=Failed to log in. Microsoft respond with error code %d.
account.methods.microsoft.logging_in=Logging in...
account.methods.microsoft.manual=You should finish authorization in the newly opened browser window. If the browser window failed to show, you can click here to copy the URL, and manually open it in your browser.
account.methods.microsoft.waiting_browser=Waiting for authorization in opened browser window...

View File

@ -67,6 +67,9 @@ account.methods=登录方式
account.methods.authlib_injector=外置登录 (authlib-injector)
account.methods.microsoft=微软登录
account.methods.microsoft.close_page=已完成微软账号授权,接下来启动器还需要完成剩余登录步骤。你已经可以关闭本页面了。
account.methods.microsoft.error.add_family=由于你未满 18 岁,你的账号必须被加入到家庭中才能登录游戏。
account.methods.microsoft.error.missing_xbox_account=你的微软账号尚未关联 XBox 账号,你必须先创建 XBox 账号,才能登录游戏。
account.methods.microsoft.error.unknown=登录失败,错误码:%d
account.methods.microsoft.logging_in=登录中...
account.methods.microsoft.manual=您需要在新打开的浏览器窗口中完成登录。若页面未能打开,您可以点击此处复制链接,并手动在浏览器中打开网页。
account.methods.microsoft.waiting_browser=等待在新打开的浏览器窗口中完成登录...

View File

@ -138,6 +138,11 @@ public class MicrosoftService {
pair("RpsTicket", "d=" + liveAccessToken))),
pair("RelyingParty", "http://auth.xboxlive.com"), pair("TokenType", "JWT")))
.accept("application/json").getJson(XBoxLiveAuthenticationResponse.class);
if (xboxResponse.errorCode != 0) {
throw new XboxAuthorizationException(xboxResponse.errorCode);
}
String uhs = (String) xboxResponse.displayClaims.xui.get(0).get("uhs");
// Authenticate Minecraft with XSTS
@ -149,6 +154,11 @@ public class MicrosoftService {
pair("UserTokens", Collections.singletonList(xboxResponse.token)))),
pair("RelyingParty", "rp://api.minecraftservices.com/"), pair("TokenType", "JWT")))
.getJson(XBoxLiveAuthenticationResponse.class);
if (xboxResponse.errorCode != 0) {
throw new XboxAuthorizationException(xboxResponse.errorCode);
}
String minecraftXstsUhs = (String) minecraftXstsResponse.displayClaims.xui.get(0).get("uhs");
if (!Objects.equals(uhs, minecraftXstsUhs)) {
throw new ServerResponseMalformedException("uhs mismatched");
@ -163,6 +173,11 @@ public class MicrosoftService {
pair("UserTokens", Collections.singletonList(xboxResponse.token)))),
pair("RelyingParty", "http://xboxlive.com"), pair("TokenType", "JWT")))
.getJson(XBoxLiveAuthenticationResponse.class);
if (xboxXstsResponse.errorCode != 0) {
throw new XboxAuthorizationException(xboxXstsResponse.errorCode);
}
String xboxXstsUhs = (String) xboxXstsResponse.displayClaims.xui.get(0).get("uhs");
if (!Objects.equals(uhs, xboxXstsUhs)) {
throw new ServerResponseMalformedException("uhs mismatched");
@ -260,6 +275,21 @@ public class MicrosoftService {
return JsonUtils.fromNonNullJson(result, MinecraftProfileResponse.class);
}
public static class XboxAuthorizationException extends AuthenticationException {
private final long errorCode;
public XboxAuthorizationException(long errorCode) {
this.errorCode = errorCode;
}
public long getErrorCode() {
return errorCode;
}
public static final long MISSING_XBOX_ACCOUNT = 2148916233L;
public static final long ADD_FAMILY = 2148916238L;
}
/**
* Error response: {"error":"invalid_grant","error_description":"The provided
* value for the 'redirect_uri' is not valid. The value must exactly match the
@ -304,6 +334,17 @@ public class MicrosoftService {
List<Map<Object, Object>> xui;
}
private static class MicrosoftErrorResponse {
@SerializedName("XErr")
long errorCode;
@SerializedName("Message")
String message;
@SerializedName("Redirect")
String redirectUrl;
}
/**
*
* Success Response: { "IssueInstant":"2020-12-07T19:52:08.4463796Z",
@ -316,7 +357,7 @@ public class MicrosoftService {
* XErr Candidates: 2148916233 = missing XBox account 2148916238 = child account
* not linked to a family
*/
private static class XBoxLiveAuthenticationResponse {
private static class XBoxLiveAuthenticationResponse extends MicrosoftErrorResponse {
@SerializedName("IssueInstant")
String issueInstant;