Zh:Microsoft Authentication Scheme: Difference between revisions
imported>AzurIce m 修改了错误的XBL身份验证请求格式 |
imported>Xiaoyi311 Add Minecraft API Apply |
||
(4 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
Minecraft正在迁移至微软账号。自2020年12月起,所有新账号已经使用了新版系统,旧的账号也将在之后迁移,详见[https://www.minecraft.net/en-us/article/java-edition-moving-house 这篇博文]。 | Minecraft正在迁移至微软账号。自2020年12月起,所有新账号已经使用了新版系统,旧的账号也将在之后迁移,详见[https://www.minecraft.net/en-us/article/java-edition-moving-house 这篇博文]。 | ||
新版系统需要多个步骤以及不同的令牌,但是最后你还是回获得一个普通的Minecraft令牌。启动游戏本身并没有改变。 | |||
== 微软OAuth流程 == | == 微软OAuth流程 == | ||
在所有这些步骤之前,你需要先通过创建一个 [https://learn.microsoft.com/zh-cn/azure/active-directory/develop/quickstart-register-app 微软 Azure 应用程序] 来获得一个客户端 ID。你''不''需要获得一个客户端密码。 | |||
你可以通过 [https://learn.microsoft.com/zh-cn/azure/active-directory/develop/v2-oauth2-auth-code-flow OAuth 2.0 授权代码流] 来获取一个访问令牌。你需要向用户显示一个登录页面,一旦完成,会重定向到一个指定的 URL,并在查询参数里传递 token。在非 web 应用程序中这需要通过搭建一个临时 HTTP 服务器来处理这个重定向。如果你不希望这样,可以使用(不那么自动化的)[https://learn.microsoft.com/zh-cn/azure/active-directory/develop/v2-oauth2-device-code 设备代码流] 代替。 | |||
不论如何,你需要把 <code>XboxLive.signin</code> 包含在认证请求的 <code>scope</code> 参数内,否则下一个终结点会报错。 | |||
< | |||
<b>请注意</b>:根据 Mojang 发布的 [https://help.minecraft.net/hc/en-us/articles/16254801392141 新Java版游戏服务API审核或应用程序流程] 规定,新建的 OAuth 应用程序必须使用此表单申请使用 Minecraft API 的使用权限,如果您的应用程序没有对应权限 <code>api.minecraftservices.com</code> 将返回 403 | |||
== XBL身份验证 == | == XBL身份验证 == | ||
Line 79: | Line 25: | ||
"AuthMethod": "RPS", | "AuthMethod": "RPS", | ||
"SiteName": "user.auth.xboxlive.com", | "SiteName": "user.auth.xboxlive.com", | ||
"RpsTicket": "d=<access_token>" // | "RpsTicket": "d=<access_token>" // 第一步中获取的访问令牌 | ||
}, | }, | ||
"RelyingParty": "http://auth.xboxlive.com", | "RelyingParty": "http://auth.xboxlive.com", | ||
Line 173: | Line 119: | ||
GET https://api.minecraftservices.com/entitlements/mcstore | GET https://api.minecraftservices.com/entitlements/mcstore | ||
访问令牌在验证文件头中:<code>Authorization: Bearer token</code> | 访问令牌在验证文件头中:<code>Authorization: Bearer token</code>。请注意,<code>Bearer</code>必须保留,<code>token</code>是上一步获取到的访问令牌。 | ||
如果用户拥有游戏,那么响应会看起来像这样: | 如果用户拥有游戏,那么响应会看起来像这样: | ||
Line 261: | Line 207: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
那么这样就可以知道所有必要的数据(MC访问令牌、用户名和uuid)来启动游戏了。干得漂亮! | |||
== 示例实现 == | == 示例实现 == | ||
这里有个简易的Java示例实现(使用了javafx和它的webview):https://github.com/MiniDigger/MiniLauncher/blob/master/launcher/src/main/java/me/minidigger/minecraftlauncher/launcher/gui/MsaFragmentController.java 。 | 这里有个简易的Java示例实现(使用了javafx和它的webview):https://github.com/MiniDigger/MiniLauncher/blob/master/launcher/src/main/java/me/minidigger/minecraftlauncher/launcher/gui/MsaFragmentController.java 。 |
Latest revision as of 07:39, 24 January 2024
Minecraft正在迁移至微软账号。自2020年12月起,所有新账号已经使用了新版系统,旧的账号也将在之后迁移,详见这篇博文。
新版系统需要多个步骤以及不同的令牌,但是最后你还是回获得一个普通的Minecraft令牌。启动游戏本身并没有改变。
微软OAuth流程
在所有这些步骤之前,你需要先通过创建一个 微软 Azure 应用程序 来获得一个客户端 ID。你不需要获得一个客户端密码。
你可以通过 OAuth 2.0 授权代码流 来获取一个访问令牌。你需要向用户显示一个登录页面,一旦完成,会重定向到一个指定的 URL,并在查询参数里传递 token。在非 web 应用程序中这需要通过搭建一个临时 HTTP 服务器来处理这个重定向。如果你不希望这样,可以使用(不那么自动化的)设备代码流 代替。
不论如何,你需要把 XboxLive.signin
包含在认证请求的 scope
参数内,否则下一个终结点会报错。
请注意:根据 Mojang 发布的 新Java版游戏服务API审核或应用程序流程 规定,新建的 OAuth 应用程序必须使用此表单申请使用 Minecraft API 的使用权限,如果您的应用程序没有对应权限 api.minecraftservices.com
将返回 403
XBL身份验证
现在,我们已通过微软身份验证,可以向xbox live进行身份验证。
我们需要发送:
POST https://user.auth.xboxlive.com/user/authenticate
{
"Properties": {
"AuthMethod": "RPS",
"SiteName": "user.auth.xboxlive.com",
"RpsTicket": "d=<access_token>" // 第一步中获取的访问令牌
},
"RelyingParty": "http://auth.xboxlive.com",
"TokenType": "JWT"
}
同样,也得设置Content-Type: application/json
以及Accept: application/json
响应看起来会像这样:
{
"IssueInstant":"2020-12-07T19:52:08.4463796Z",
"NotAfter":"2020-12-21T19:52:08.4463796Z",
"Token":"token", // 保存它,这是你的xbl令牌
"DisplayClaims":{
"xui":[
{
"uhs":"uhs" // 保存它
}
]
}
}
我们需要保存这里的Token
和uhs
。uhs是user hash的缩写,为用户信息哈希值。
XSTS身份验证
现在,我们已经通过XBL进行了身份验证,我们需要获取XSTS令牌,我们可以使用它来登录Minecraft。
POST https://xsts.auth.xboxlive.com/xsts/authorize
{
"Properties": {
"SandboxId": "RETAIL",
"UserTokens": [
"xbl_token" // from above
]
},
"RelyingParty": "rp://api.minecraftservices.com/",
"TokenType": "JWT"
}
同样还是设置Content-Type: application/json
以及Accept: application/json
响应看起来会像这样:
{
"IssueInstant":"2020-12-07T19:52:09.2345095Z",
"NotAfter":"2020-12-08T11:52:09.2345095Z",
"Token":"token", // 保存它,这是你的xsts令牌
"DisplayClaims":{
"xui":[
{
"uhs":"" // 与上个请求相同
}
]
}
}
Minecraft身份验证
现在,我们终于可以回到Minecraft身上了,上一各请求中获取的XSTS令牌允许我们验证Minecraft。
POST https://api.minecraftservices.com/authentication/login_with_xbox
{
"identityToken": "XBL3.0 x=<uhs>;<xsts_token>"
}
响应:
{
"username" : "some uuid", // 这并不是账号的uuid
"roles" : [ ],
"access_token" : "minecraft access token", // jwt,你的老朋友Minecraft访问令牌
"token_type" : "Bearer",
"expires_in" : 86400
}
这个访问令牌(access_token
)允许我们启动游戏,但是,我们甚至还没有检查该账号是否拥有游戏。之前我们做的所有工作都是与微软账号进行的!
检查游戏拥有情况
那么现在让我们使用MC的访问令牌来检查该账号是否包含产品许可。
GET https://api.minecraftservices.com/entitlements/mcstore
访问令牌在验证文件头中:Authorization: Bearer token
。请注意,Bearer
必须保留,token
是上一步获取到的访问令牌。
如果用户拥有游戏,那么响应会看起来像这样:
{
"items" : [ {
"name" : "product_minecraft",
"signature" : "jwt sig"
}, {
"name" : "game_minecraft",
"signature" : "jwt sig"
} ],
"signature" : "jwt sig",
"keyId" : "1"
}
第一个jwts会包含值:
{
"typ": "JWT",
"alg": "RS256",
"kid": "1"
}.{
"signerId": "2535416586892404",
"name": "product_minecraft"
}.[Signature]
最后一个jwt看起来是这样解码的:
{
"typ": "JWT",
"alg": "RS256",
"kid": "1"
}.{
"entitlements": [
{
"name": "product_minecraft"
},
{
"name": "game_minecraft"
}
],
"signerId": "2535416586892404"
}.[Signature]
如果该账号没有拥有游戏,那么项目为空。
获取档案
现在我们知道了该账号拥有游戏,那么可以获取他的档案来得到uuid:
GET https://api.minecraftservices.com/minecraft/profile
同样,访问令牌在验证文件头中:Authorization: Bearer token
如果账号拥有游戏,响应看起来会像这样:
{
"id" : "986dec87b7ec47ff89ff033fdb95c4b5", // 账号的真实uuid
"name" : "HowDoesAuthWork", // 该账号的mc用户名
"skins" : [ {
"id" : "6a6e65e5-76dd-4c3c-a625-162924514568",
"state" : "ACTIVE",
"url" : "http://textures.minecraft.net/texture/1a4af718455d4aab528e7a61f86fa25e6a369d1768dcb13f7df319a713eb810b",
"variant" : "CLASSIC",
"alias" : "STEVE"
} ],
"capes" : [ ]
}
否则会看起来像这样:
{
"path" : "/minecraft/profile",
"errorType" : "NOT_FOUND",
"error" : "NOT_FOUND",
"errorMessage" : "The server has not found anything matching the request URI",
"developerMessage" : "The server has not found anything matching the request URI"
}
那么这样就可以知道所有必要的数据(MC访问令牌、用户名和uuid)来启动游戏了。干得漂亮!
示例实现
这里有个简易的Java示例实现(使用了javafx和它的webview):https://github.com/MiniDigger/MiniLauncher/blob/master/launcher/src/main/java/me/minidigger/minecraftlauncher/launcher/gui/MsaFragmentController.java 。