14 KiB
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。
所有 POST
和 PUT
端点(出于历史原因,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
。依据错误类型,可能含有其他键,但 error
和 errcode
两个键必须始终存在。
部分标准错误码如下:
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>
通常为小写 email
或 msisdn
,<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 必须通过 /lookup
的 pepper
参数一并提交。
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" %}}