MENU

浅谈使用 Microsoft OAuth 身份验证流的 Minecraft 账户鉴权

• September 28, 2022 • 编程心得,技术分享阅读设置

前言

随着 Friendship Studio 对于 Friendship org 数字化建设的推进,Frienship Cloud 服务系统的建设日益迫切。这一系统最基础的要求就是基于可信源的 Minecraft 账户和 QQ 账户鉴权并绑定,经过本人以及 @AsakiRain 的探索与研究,总结出了使用 Microsoft OAuth2.0 授权代码流的 Minecraft 账户身份验证服务路线。


开发准备

首先,使用 OAuth 系统必须完成以下前置检查单:

  1. 可用的 Azure 账户(付费、免费或教育账户皆可)
  2. 在 Azure Active Directory (AD) 中注册一个应用,你应该:

    • 决定一个合适的应用名(这通常对功能实现无关紧要)
    • “受支持的帐户类型” 选择 “仅 Microsoft 个人帐户”
    • “重定向 URI” 填入用户在完成 Microsoft 账户登录,Microsoft 为你重定向的地址
    • 进入“概述”页面,提取“应用程序(客户端) ID”

没有合适的重定向URI?

如果你处于调试前期,缺少合适的设置,可设置为 localhost ,然后在重定向页面的地址栏中手动提取Token。你的重定向地址必须在 Azure 控制台声明,否则不能访问!

请不要忽略“重定向URI”

虽然 Azure 认为它“可选”,但是如果你缺少此项,应用程序将无法正确返回后续所需的令牌凭据,后续接口访问调用 必须 使用由重定向URI返回的令牌凭据!


项目实现

OAuth2.0 认证流

用户唤起 Microsoft 认证请求后,你需要将他(或她,下略)重定向到此位置

POST https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id={你的AD应用程序(客户端)ID}&response_type=token&redirect_uri={你的重定向URI}&scope=XboxLive.signin+offline_access&state={状态值}&response_mode=fragment

什么是状态值?

他是同时随令牌响应返回的请求中所包含的值。 可以是想要的任何内容的字符串。 随机生成的唯一值通常用于 防止跨站点请求伪造攻击。 该值还可用于在身份验证请求发生前,对有关用户在应用中的状态信息进行编码。 例如,它可以对用户所在的页面或视图进行编码。
这个值是可选值,你可以根据自身需要添加。

随后,如果用户成功登陆了 Microsoft 账户,OAuth 页面会将你重定向至你设定的 URI。此时,你应该从 URI 中提取用户的OAuth Access Token。此令牌有效时间应为3600秒,即一小时。

XBL 认证

将你在上一步获得的 OAuth Access Token 包装为请求,不要去掉d=前缀

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"
 }

请注意,你必须添加这两个Headers标签才能正常使用此请求以及后续请求体为 Json 格式的请求:Content-Type: application/jsonAccept: application/json。同时,你应启用 SSL 协议请求。

这个请求返回如下:

 {
   "IssueInstant":"2020-12-07T19:52:08.4463796Z",
   "NotAfter":"2020-12-21T19:52:08.4463796Z",
   "Token":"token",
   "DisplayClaims":{
      "xui":[
         {
            "uhs":"userhash"
         }
      ]
   }
 }

保存其中的Tokenuhs,进行下一步。

XSTS 认证

要登录 Minecraft 网络,需要使用 XSTS 提供的令牌,获取请求如下:

POST https://xsts.auth.xboxlive.com/xsts/authorize
 {
    "Properties": {
        "SandboxId": "RETAIL",
        "UserTokens": [
            "xbl_token" 
        ]
    },
    "RelyingParty": "rp://api.minecraftservices.com/",
    "TokenType": "JWT"
 }

xbl_token填入上一步保存的Token值。不要忘了请求头
由于本文不涉及 Minecraft BE 版本的鉴权,因此不对分支路线作说明,两者流程从此步开始也不尽相同。
如果返回 401 错误,说明用户 XboxLive 账户状态异常,你应该返回Message的内容提醒其需要处置。
一切正常的话,你将收到如下回应:

{
   "IssueInstant":"2020-12-07T19:52:09.2345095Z",
   "NotAfter":"2020-12-08T11:52:09.2345095Z",
   "Token":"token", // save this, this is your xsts token
   "DisplayClaims":{
      "xui":[
         {
            "uhs":"userhash"
         }
      ]
   }
}

保存其中的Token,此处的uhs应和上一步时显示的一致。

Minecraft 认证

终于踏入了 Minecraft 的地盘(但这不是终点!),接下来我们取得 Minecraft 的认证:

POST https://api.minecraftservices.com/authentication/login_with_xbox
 {
    "identityToken": "XBL3.0 x=<userhash>;<xsts_token>"
 }

返回如下:

 {
  "username" : "some uuid", // this is not the uuid of the account
  "roles" : [ ],
  "access_token" : "minecraft access token", 
  "token_type" : "Bearer",
  "expires_in" : 86400
 }

完美!看到那个access_token了吗?它已经可以用于启动 Minecraft 了(启动器会用到它),但它还不能用于检查 Minecraft 的持有情况,我们还需要再深入些...
我们继续。

检查 Minecraft 所有权

对于 Friendship Cloud,我们只想获得用户的 Minecraft 的游戏信息,因此我们只读取 Minecraft 账户信息。
在前面我们提到的两个请求头之后再添加一个新请求头:Authorization: Bearer <Minecraft Access Token> 不要漏掉 Bearer
发送一个 GET 请求:

GET https://api.minecraftservices.com/minecraft/profile

如果用户真的拥有 Minecraft JE,服务器会返回详尽的用户个人资料,FSC 会保存其中的 UUID 和用户名。
当然,如果用户什么也没有,返回的值会出现一大堆错误来告诉你用户没有你想查找的内容。

到这里,你已经完成了 Minecraft 的账户鉴权。你可以取得无论是网页认证或是启动器启动的一切资料:Access TokenUUID、用户名、皮肤源文件,甚至是皮肤形态的设置。


项目工作流程

希望此流程图能让你对整个流程理解更加清晰。

st=>start: 用户发起绑定 Microsoft 账户请求
e1=>end: 绑定失败或异常终止,鉴权结束
e2=>end: 绑定成功,鉴权结束
op1=>operation: 调用 OAuth2.0 系统
cond1=>condition: 用户登录 OAuth 系统
op2=>operation: 调用 XBL 服务
op3=>operation: 调用 XSTS 服务
cond2=>condition: XSTS 检查账户合法性
cond3=>condition: 检查 Minecraft 账户资料
op4=>operation: 提取用户名,构建头像截图
io=>inputoutput: 向用户展示用户名和皮肤头像
cond4=>condition: 用户确认是否为本人账户

st->op1->cond1(yes)->op2->op3->cond2(yes)->cond3(yes)->op4->io->cond4(yes)->e2
cond1(no)->e1
cond2(no)->e1
cond3(no)->e1
cond4(no)->e1

结语

可以看出,如果没有对于 Microsoft 认证系统有一定研究,要取得最后的消息还是需要有一定复杂的操作。希望本文能帮助你解决你编程道路的一个小障碍,祝你探索愉快!

实现样例

这是使用 Python 编写,实现了以上步骤与功能的参考样例:

致谢、参考与引用

  1. Microsoft 标识平台和 OAuth 2.0 授权代码流 Microsoft Learn 文档
  2. Microsoft Authentication Scheme wiki.vg

感谢 @AsakiRain 在我开发路上的一路相伴。他作为一名优秀的 WEB 开发者和我的挚友,为我指出了许多问题并提出了大量富有建设性的建议,为 Friendship Cloud 系统的建设下了许多功夫。在此表达谢意!

Last Modified: October 6, 2022
Leave a Comment

2 Comments
  1. 博主,能不能开源认证用的python脚本啊

    1. @SakuyaRain可以的,这就办。