Synapse Refresh Tokens 完全指南配置访问令牌过期、会话刷新与非活跃会话登出【免费下载链接】synapseSynapse: Matrix homeserver written in Python/Twisted.项目地址: https://gitcode.com/gh_mirrors/sy/synapse导读Refresh Tokens刷新令牌是 SynapsePython/Twisted 编写的 Matrix 家服务器自 1.49 版本起正式支持的安全机制对齐 [MSC2918] 规范。本文以官方配置文档为骨架结合仓库源码与配置校验实现系统讲解 refresh token 的工作原理、四个核心配置参数、如何用令牌过期自动登出非活跃会话以及 L/S 双阈值取值模型帮助管理员在降低令牌泄露风险与避免频繁重登录打扰用户之间找到平衡。背景与动机为什么需要 Refresh Tokens在 Matrix 协议中用户会话由access token访问令牌标识。用户登录时家服务器为每个会话签发一个唯一的 access token客户端后续所有请求都携带该令牌令牌必须严格保密因为它等价于对用户账号的完全访问权。传统上也是 Synapse 默认行为这些 access token永久有效除非用户显式退出登录。这带来一个两难问题从安全角度令牌泄露造成的损害与令牌有效期成正比——希望 access token 尽快过期从体验角度频繁强制用户重新认证重新输入密码登录过于不便。Refresh token 正是为调和这对矛盾而生——它在短生命周期 access token 带来的大部分安全收益之上避免了频繁重登录的麻烦。这一概念同样存在于 OAuth 2 规范RFC 6749 §1.5中熟悉 OAuth 2 的读者可以类比理解。启用 refresh token 后登录时家服务器会同时签发一个 access token 和一个 refresh tokenaccess token 在预定时间后过期但在过期前其用法与从前完全一致当 access token 接近过期或已经过期时客户端向家服务器出示 refresh token家服务器为其签发新的 access token 和新的 refresh token旧 refresh token 随即失效详见下文轮换语义refresh token 还使得管理员能够将长期无活动的会话提前登出而不必等会话自然结束。关于旧 refresh token 立即失效的精确说明为防止客户端在刷新令牌的途中因断连而丢失凭证旧 refresh token 只有在新 access token 被实际使用过一次之后才真正失效。对大多数场景而言旧令牌被作废的简化理解已足够。Refresh Token 的工作机制源码视角从源码可以完整还原该机制的实现链路。登录阶段客户端显式请求 refresh token在 登录接口实现 中服务端通过以下逻辑决定是否签发 refresh token# synapse/rest/client/login.py self._refresh_tokens_enabled ( hs.config.registration.refreshable_access_token_lifetime is not None ) ... client_requested_refresh_token login_submission.get(refresh_token) ... should_issue_refresh_token ( self._refresh_tokens_enabled and client_requested_refresh_token )两个关键事实功能开关refresh token 机制是否启用取决于registration.refreshable_access_token_lifetime是否被配置为None该参数默认值为5m即默认启用客户端必须显式请求客户端需要在登录请求体中携带refresh_token: true服务端才会签发 refresh token。登录成功响应中除access_token、user_id、device_id外还会附带refresh_token字段若 access token 有过期时间还会附带expires_in_ms字段见 登录响应构造逻辑。刷新阶段POST /_matrix/client/v3/refresh刷新由 RefreshTokenServlet 处理路由为client_patterns(/refresh$)即对应 Matrix 客户端 API 的/_matrix/client/v3/refresh端点。请求体为一个 JSON 对象{ refresh_token: syr_...旧 refresh token }服务端流程RefreshTokenServlet.on_POST校验请求体中存在且为字符串类型的refresh_token字段依据配置计算新令牌的过期时刻access_valid_until_ms now refreshable_access_token_lifetime、refresh_valid_until_ms now refresh_token_lifetime对应参数未配置则为None表示永不过期调用AuthHandler.refresh_tokensynapse/handlers/auth.py#L767-L871完成令牌轮换返回200及{access_token: ..., refresh_token: ..., expires_in_ms: ...}expires_in_ms仅在令牌确实过期时出现。底层核心AuthHandler.refresh_token的轮换与校验refresh_token 核心实现 依次完成以下步骤签名/形状校验_verify_refresh_tokensynapse/handlers/auth.py#L873-L899refresh token 形如syr_localpart_rand_crc以syr_为前缀末段为基于crc32与 base62 编码的校验和形状不符直接拒绝存在性校验在数据库中查找该令牌不存在则返回M_UNKNOWN_TOKEN轮换状态校验若该令牌的has_next_access_token_been_used或has_next_refresh_token_been_refreshed已被置位即上一轮轮换产出的新令牌已被使用则旧令牌返回M_FORBIDDEN——这正是旧 refresh token 在新 access token 首次使用后才失效的实现体现过期校验令牌自身的expiry_ts已过则拒绝会话上限封顶若存在ultimate_session_expiry_ts由session_lifetime决定则新签发的 access token 与 refresh token 的过期时刻均取自身寿命与会话上限的较小值确保整个会话的生命周期严格不超过上限。新令牌通过create_refresh_token_for_user_idsynapse/handlers/auth.py#L920-L952与create_access_token_for_user_idsynapse/handlers/auth.py#L954-L988生成并入库旧令牌经replace_refresh_token完成数据库层面的轮换记录随后返回新令牌对。注意事项Caveats使用 refresh token 机制时需知晓以下几点双令牌同时泄露若第三方同时获得你的 access token 与 refresh token他们仍能持续访问你的会话。但这仍是改进你自己会发现会话过期且 refresh token 无法使用——这是会话被他人劫持的明确信号你只需重新登录并终止该会话即可。而在过去的长效 access token 时代被窃取可能长期不被察觉。客户端需实现支持refresh token 只有被客户端实现才能真正发挥作用。是否向不支持 refresh token 的客户端签发长效 access token由家服务器管理员决定。为兼容性考虑在客户端支持普及之前通常建议继续签发。支持 refresh token 的客户端用户依然能获得增强的安全性由于会话无法被降级为长效 access token这等于把选择权交给了用户。在封闭环境中所有用户使用已知客户端管理员可以确认客户端是否支持 refresh token。此时可将nonrefreshable_access_token_lifetime设得很短从而为不支持 refresh token 的客户端也提供相近的安全级别。配置指南registration段落的四个参数所有相关配置均位于registration配置段落。下表汇总了四个参数及其默认值默认值来源于 配置文件解析实现配置项作用建议值默认值session_lifetime会话最大长度即使不断刷新也会在此时间后强制要求重新登录通常不设置无限或设长数月/数年None无限refreshable_access_token_lifetime支持 refresh token 的客户端所获 access token 的寿命应设短推荐5m5mnonrefreshable_access_token_lifetime不支持 refresh token 的客户端所获 access token 的寿命想强制使用 refresh token 就设短不想打扰老客户端就设长None整个会话期间有效refresh_token_lifetimerefresh token 的寿命即客户端须在此期限内完成至少一次刷新才能维持会话无需登出非活跃会话时可设长或不设无限太短会困扰低频连接的客户端None无限重要提示以上四个参数只在令牌创建时登录或刷新时生效修改配置不会追溯影响已存在的令牌。参数间的一致性校验配置加载逻辑 内置了三组一致性校验当session_lifetime同时配置了refreshable_access_token_lifetime、nonrefreshable_access_token_lifetime或refresh_token_lifetime中任意一项且该项超过session_lifetime时Synapse 会直接抛出ConfigError拒绝启动并提示诸如Both session_lifetime and refreshable_access_token_lifetime configuration options have been set, but refreshable_access_token_lifetime exceeds session_lifetime!这从配置层面保证了会话上限始终不小于任何令牌寿命的语义一致性。各参数的设计意图session_lifetime定义一次会话的绝对上限。无论中间刷新多少次到达该时刻后客户端必须重新登录。适合作为账号安全策略的兜底。refreshable_access_token_lifetime该参数是否为None直接决定了 refresh token 机制是否启用见上文登录逻辑。设短如 5 分钟可将泄露 access token的破坏窗口压缩到极小。nonrefreshable_access_token_lifetime面向不支持 refresh token 的旧客户端。它是强制全量使用 refresh token的关键杠杆设得极短甚至 0等于逼迫所有客户端走刷新流程。refresh_token_lifetime与session_lifetime的差异在于它是滑动窗口——只要客户端在窗口内成功刷新会话就能延续。设得比refreshable_access_token_lifetime短会形同虚设还会导致低频客户端移动端、不活跃用户频繁被迫重新登录。实战场景用 Refresh Token 过期登出非活跃会话若希望长时间无活动的会话被强制登出只需同时启用 access token 过期与 refresh token 过期。原理很直接客户端要维持账号的有效凭证就必须在refresh_token_lifetime周期内至少刷新一次不刷新即过期会话随之失效。下文假设refresh_token_lifetime大于refreshable_access_token_lifetime这是推荐的取值前提。注意该机制只影响使用 refresh token 的会话。建议同时把nonrefreshable_access_token_lifetime设短防止不支持 refresh token 的客户端绕过此策略。如何取值允许一定宽限期的 L/S 模型实践中通常希望容忍客户端短暂的非活动期例如应对客户端连接的小型故障即同时满足两个要求非活动时长超过L必须登出会话非活动时长小于S不得登出会话。该模型基于最弱假设活跃客户端只会在必要时刻刷新以维持有效 access token不会更早。实际客户端往往更频繁地刷新但上述两个要求依然成立——即模型结果对真实客户端是保守成立的。满足该模型只需refresh_token_lifetime设为Lrefreshable_access_token_lifetime设为L - S。示例若要求非活动超过 7 天必须登出L 7d且非活动 3 天内不得登出S 3d则配置为registration: session_lifetime: 30d refreshable_access_token_lifetime: 4d refresh_token_lifetime: 7d nonrefreshable_access_token_lifetime: 4d推导逻辑access token 寿命4d 7d - 3d客户端最迟在第 4 天必须刷新只要它在S 3d内保持活跃就能在过期前完成刷新会话不受影响一旦非活跃超过L 7drefresh token 本身也过期会话必然被登出。版本与兼容性说明Refresh token 支持自Synapse 1.49起提供更早的某些版本曾支持 [MSC2918] 的早期实验性草案与现行为不兼容。该机制依赖 Matrix 客户端 API 的/refresh端点对应 RefreshTokenServlet且要求客户端在登录时显式请求 refresh token因此客户端支持是必要条件。仓库中的 登录/刷新相关测试 与 注册配置校验测试 覆盖了令牌签发、刷新轮换、参数越界报错等行为可作为理解各参数语义与边界条件的参考。结语Refresh token 机制让 Synapse 管理员得以用很小的用户体验代价换来 access token 泄露风险的显著降低并天然支持非活跃会话自动登出等安全策略。配置上只需把握四个参数session_lifetime定会话上限、refreshable_access_token_lifetime定可刷新令牌寿命、nonrefreshable_access_token_lifetime定老客户端令牌寿命、refresh_token_lifetime定刷新窗口配合 L/S 取值模型即可在安全与便利之间精确取点。相关实现与校验可进一步查阅 synapse/config/registration.py、synapse/rest/client/login.py 与 synapse/handlers/auth.py。【免费下载链接】synapseSynapse: Matrix homeserver written in Python/Twisted.项目地址: https://gitcode.com/gh_mirrors/sy/synapse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考