docs-matrix-spec/locales/zh-Hans/identity-service-api.md
2025-04-20 16:13:37 +08:00

14 KiB
Raw Blame History

title weight type
身份服务 API 40 docs

{{< boxes/warning >}} 本页面的翻译未经核对,可能存在翻译质量不佳、错翻、漏翻等情况。您可以在 Forgejo 存储库 打开 Issue、提交 Pull Request 或邮件联系我们提出改进建议和参与翻译与核对。 {{< /boxes/warning >}}

Matrix 的客户端-服务器与服务器-服务器 API 主要使用 Matrix 用户标识符。在某些情况下我们需要以其他“第三方”标识符或“3PID”如电子邮件地址或电话号码来引用用户。本身份服务规范描述了如何建立、验证和使用第三方标识符与 Matrix 用户标识符之间的映射。理论上,本规范可适用于任意 3PID但实际上目前仅针对电子邮件地址和电话号码进行了具体实现。

基本原则

身份服务器的目的是验证、存储并响应有关用户身份的问题。具体来说,它存储如下关联:“标识符 X 与标识符 Y 代表同一用户”其中这些身份可存在于不同系统如电子邮件地址、电话号码、Matrix 用户 ID 等)中。

身份服务器拥有若干私钥-公钥对。当被查询某项关联时,它会使用其私钥对该关联的详细信息进行签名。客户端可通过验证身份服务器公钥的签名,来校验关于关联的声明。

通常情况下,身份服务器被视为可靠的权威。它们并不总能提供已验证关联的证据,但会声称已完成验证。具体信任哪台身份服务器,由客户端自行决定。

3PID 类型详见3PID 类型附录。

API 标准

Matrix 身份服务器通信的强制基线是通过 HTTP API 交换 JSON 对象。通信必须使用 HTTPS。

所有 POSTPUT 端点(出于历史原因,POST /_matrix/identity/v2/account/logout 除外都要求客户端在请求体中提交一个可能为空的JSON 对象。对于带有 JSON 请求体的请求,客户端应提供 Content-Type: application/json 头,但这非强制要求。

同样,所有端点都需返回 JSON 对象。服务器返回 JSON 时,必须包括 Content-Type: application/json 响应头。

所有请求或响应中的 JSON 数据,必须采用 UTF-8 编码。

标准错误响应

若在 Matrix API 层发生错误,必须返回“标准错误响应”。其格式为如下 JSON 对象:

{
  "errcode": "<error code>",
  "error": "<error message>"
}

error 字符串为人类可读的错误信息,通常描述出错原因。errcode 字符串为唯一字符串,便于处理错误信息,如 M_FORBIDDEN。依据错误类型,可能含有其他键,但 errorerrcode 两个键必须始终存在。

部分标准错误码如下:

M_NOT_FOUND 请求的资源无法找到。

M_MISSING_PARAMS 请求缺少一个或多个参数。

M_INVALID_PARAM 请求包含一个或多个无效参数。

M_SESSION_NOT_VALIDATED Session 尚未验证。

M_NO_VALID_SESSION 根据提供参数找不到相关 Session。

M_SESSION_EXPIRED Session 已过期,需重新创建。

M_INVALID_EMAIL 提供的电子邮件地址无效。

M_EMAIL_SEND_ERROR 发送邮件时出错。通常发生在验证给定邮箱所有权时。

M_INVALID_ADDRESS 提供的第三方地址无效。

M_SEND_ERROR 发送通知时出错。通常见于验证第三方地址所有权时。

M_UNRECOGNIZED 请求中包含未识别的值,如未知的 token 或 medium。

当服务器无法理解请求时,也会使用此响应。若端点未实现,返回 HTTP 状态码 404若实现了但使用了错误的 HTTP 方法,返回 405。

M_THREEPID_IN_USE 第三方标识符已被他人使用。该错误通常会包含额外的 mxid 字段,以标明该 3PID 的所有者。

M_UNKNOWN 发生未知错误。

隐私

身份信息关系隐私敏感。身份服务器存在的目的是提供身份信息但访问应受到限制以避免泄露潜在的敏感数据。尤其应避免构建大规模的身份关联网络。因此API 通常允许将 3PID 映射到 Matrix 用户身份,但禁止反向映射(即不能查询某 Matrix 用户 ID 关联有哪些 3PID也不能批量获取一个 3PID 关联的全部身份)。

Web 浏览器客户端

部分客户端可能在 Web 浏览器或类似环境下运行。此时身份服务器应响应预检pre-flight请求并在所有请求中返回跨域资源共享CORS头。

当客户端以 OPTIONS 请求访问服务器时,服务器需返回对应路由的 CORS 头。建议服务器所有请求返回以下 CORS 头:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization

API 版本检查

{{% http-api spec="identity" api="versions" %}}

认证

身份服务 API 的大多数端点都要求认证,以确保请求用户已接受所有相关政策,并有权限发起请求。

身份服务器采用类似 Client-Server API 的访问令牌方案进行用户认证。身份服务器发放的访问令牌不能用于认证 Client-Server API 请求。

访问令牌可通过请求头以 Bearer 方式提供:Authorization: Bearer TheTokenHere

客户端也可以(但不推荐)通过查询字符串参数提供访问令牌:access_token=TheTokenHere。为避免令牌泄漏到访问日志或 HTTP 日志,不推荐客户端再采用这种方式。

身份服务器必须同时支持这两种方式。

{{% boxes/note %}} {{% changed-in v="1.11" %}} 通过查询字符串参数传递访问令牌已被弃用。 {{% /boxes/note %}}

若缺少或认证凭据无效HTTP 响应为 401错误码为 M_UNAUTHORIZED

{{% http-api spec="identity" api="v2_auth" %}}

服务条款

身份服务器建议配置服务条款(或类似政策),以确保用户同意服务器处理其数据。为此,身份服务器可以对几乎所有需认证的 API 端点返回 HTTP 403 和错误码 M_TERMS_NOT_SIGNED。该状态表明,用户需接受最新服务条款后才能继续操作。

所有支持认证的端点都可能返回 M_TERMS_NOT_SIGNED 错误。收到此错误后,客户端应调用 GET /terms 获取服务器提供的服务条款,并与用户的 m.accepted_terms 账号数据(下文介绍)进行比较,再向用户展示尚未接受的服务条款,并提供同意的选项。用户选择后(如适用),客户端调用 POST /terms 提交已接受的条款。服务器不可假定客户端会一次性提交所有待同意的条款,客户端也不可假定服务器接收到这些条款后就不会再次响应 M_TERMS_NOT_SIGNED。用户刚同意的条款会追加到 m.accepted_terms

{{% event event="m.accepted_terms" %}}

{{% http-api spec="identity" api="v2_terms" %}}

状态检查

{{% http-api spec="identity" api="v2_ping" %}}

密钥管理

身份服务器拥有若干长期公钥-私钥对。命名方式为 算法:标识符,如 ed25519:0。签名关联时,遵循标准的签名 JSON算法。

身份服务器还可以管理一些短期公私钥对,这些密钥的用途和生命周期可与长期密钥不同。

{{% http-api spec="identity" api="v2_pubkey" %}}

关联查询

{{% http-api spec="identity" api="v2_lookup" %}}

客户端行为

在执行查询前,客户端应优先请求 /hash_details 端点,确定服务器支持哪些算法(详见下文)。客户端获取该信息后,形成相应的 /lookup 请求以从服务器获取已知绑定关系。

客户端必须至少支持 sha256 算法。

服务器行为

服务器收到 /lookup 请求后,将查询与其已知的绑定比较,必要时对本地存储的标识进行哈希以确定是否与请求完全匹配。

服务器必须至少支持 sha256 算法。

算法

部分算法在规范中有定义;如有其他需求,客户端和服务器可通过 /hash_details 协商格式。

sha256

客户端与服务器必须至少支持此算法,并且它也是推荐用于查询的算法。

采用此算法时,客户端将查询项转换为以空格分隔的字符串,格式为 <address> <medium> <pepper><pepper> 取自 /hash_details<medium> 通常为小写 emailmsisdn<address> 即要查询的 3PID。例如若客户端要查询 alice@example.org 的绑定关系,格式为 alice@example.org email ThePepperGoesHere

{{% boxes/rationale %}} 将 medium 与 pepper 附加到 address可避免每个 3PID 前缀相同,提升哈希函数抗预计算攻击能力。 {{% /boxes/rationale %}}

每条格式化字符串经 SHA-256参见 RFC 4634)处理后,结果用 URL-Safe Unpadded Base64 编码(与 room version 4 的事件 ID 格式 类似)。

如使用 pepper matrixrocks,示例查询如下:

"alice@example.com email matrixrocks" -> "4kenr7N9drpCJ4AfalmlGQVsOn3o2RHjkADUpXJWZUc"
"bob@example.com email matrixrocks"   -> "LJwSazmv46n0hlMlsb_iYxI0_HXEqy_yj6Jm636cdT8"
"18005552067 msisdn matrixrocks"      -> "nlo35_T5fzSGZzJApqu8lgIudJvmOQtDaHtr-I4rU7I"

哈希后的字符串集作为 /lookup 请求体内的 addresses 数组。注意,使用的 pepper 必须通过 /lookuppepper 参数一并提交。

none

此算法在身份服务器上执行明文查询。若因安全原因不宜传播明文标识,一般不推荐用该算法,但在某些场景(如基于 LDAP 的身份服务器)无法使用哈希,因此允许(或可选地,客户端)采用该算法查询。

sha256 类似,客户端将查询项格式化为 <address> <medium> 的空格分隔字符串,不含 <pepper>。例如,要查询 alice@example.org 的绑定,格式为 alice@example.org email

格式化字符串作为 /lookup 请求体内的 addresses。注意仍需提供 pepper(以保证客户端先正确查询了 /hash_details)。

安全性注意事项

{{% boxes/note %}} 请参考 MSC2134,其中详细阐述了本节规范的安全考量。此处仅简述规范设计的高层原因。 {{% /boxes/note %}}

通常,/lookup 端点用于客户端拥有某 3PID但希望获取对应的 Matrix 用户 ID 的场景。客户端常在邀请新用户入群或遍历通讯录查找未发现的 Matrix 用户时,用到此接口。恶意身份服务器若能收集到这些明文数据,可能滥用之。为保护未关联 Matrix ID 的 3PID 用户隐私,规范尽量提升批量收集 3PID 的难度。

{{% boxes/rationale %}} 虽然哈希不能百分百防止收集,但能显著增加批量收集标识的成本。手机号码通过哈希也难以完全隐匿,但这仍优于不加密。

另一种替代方案如 bcrypt 等多轮哈希算法,但考虑到需兼顾移动端与低性能设备,仍须保持加密过程较轻量。 {{% /boxes/rationale %}}

客户端应警惕服务器很久不轮换 pepper或使用弱 pepper这可能表明服务器试图暴力破解或利用彩虹表反查地址。同样支持 none 算法的客户端,至少应向用户警示明文发送标识给身份服务器存在的风险。

某些标识(如手机号、电邮域名、已泄露地址)即使经哈希,仍可通过预计算的彩虹表逆推出原文。例如,手机号一般为 12 位左右,比邮箱更易被攻击。

建立关联

创建关联的流程基于 Session 会话。

在 Session 内,用户可证明其拥有某 3PID。一旦验证通过用户即可将该 3PID 与 Matrix 用户 ID 关联。注意此流程的认证仅为单向,即用户可将任意已验证 3PID 关联到任意 Matrix 用户 ID例如我可把自有邮箱地址与 @billg:microsoft.com 关联。

Session 有时效性:会话初建或发生验证时被认为已修改。只有在距离上次修改 24 小时内Session 才可检查或执行验证。逾期后须新建 Session。

会话发起时,客户端请求对应 /requestToken 端点。身份服务器向用户发送验证 token用户将该 token 提供给客户端,客户端再提交到 /submitToken 端点,整个会话结束。此时,客户端可选择 /bind 该 3PID也可以留给其他实体进行绑定。

验证 token 格式

验证 token 的格式由身份服务器自行决定,应适合 3PID 类型(如不宜让用户从短信复制一长串带标点的口令)。

身份服务器采用何种格式皆可,但 token 必须不超过 255 个 Unicode 码点。客户端必须保持 token 不变地传递。

电子邮件关联

{{% http-api spec="identity" api="v2_email_associations" %}}

手机号关联

{{% http-api spec="identity" api="v2_phone_associations" %}}

通用

{{% http-api spec="identity" api="v2_associations" %}}

邀请存储

身份服务器可存储针对用户 3PID 的待处理邀请,这些邀请将在 3PID 绑定至 Matrix 用户 ID 后检索到,并可通知用户或供后续查询。

稍后,若 3PID 持有者将其绑定到 Matrix 用户 ID身份服务器会尝试通过 /3pid/onbind 端点向该 Matrix 用户的 homeserver 发送 HTTP POST 请求。请求必须由身份服务器某长期私钥签名。

{{% http-api spec="identity" api="v2_store_invite" %}}

临时邀请签名

为支持无法自行进行加密的客户端,身份服务器可提供部分加密能力,帮助其接受邀请。虽然这不如客户端自有加密安全,但在某些场景下仍有用。

{{% http-api spec="identity" api="v2_invitation_signing" %}}