- 状态:已接受
- 日期:2026-07
背景
Jira Cloud REST API 的授权模型有两种:API Token(Basic Auth,绑定用户)和 OAuth 2.0 3LO(三方授权,适用于 SaaS 代用户操作场景)。对于多租户集成场景,每个租户需要授权自己的 Jira 站点,API Token 方案无法安全地管理多租户凭据。
Atlassian 的 OAuth 2.0 实现使用旋转刷新令牌(rotating refresh token)——每次用刷新令牌获取新的访问令牌时,旧的刷新令牌同时失效。这在多实例部署或并发请求场景下会导致竞态条件。
决策
Jira Cloud 集成使用资源级 OAuth 2.0 3LO,配合原子旋转刷新令牌的 CAS(Compare-And-Swap)存储。
核心约束:
- 单站点绑定:一次 OAuth 授权只绑定一个 Jira 站点(Cloud ID),不允许跨站点操作。
- 连接器生成的 JQL 限定:只使用连接器代码生成的 JQL 查询,不直接暴露用户输入的 JQL,防止 JQL 注入。
- 首期切片不含写操作:第一版实现只读取工单、项目和用户数据,不在首期暴露创建/更新/删除操作。
- Webhook 作为触发器而非变更日志:Webhook 通知用于触发数据同步,不依赖 Webhook 记录完整变更历史。
- 原子旋转刷新令牌:刷新令牌的交换使用 CAS 操作保证原子性——如果存储中的令牌已被其他实例更新,当前操作放弃。
理由
- OAuth 2.0 3LO 是 Atlassian 推荐的 SaaS 代用户操作方案,用户不需要在连接器应用中输入密码。
- 资源级授权让用户精确控制连接器能访问哪些站点和资源。
- 旋转刷新令牌是 Atlassian 的安全设计(令牌泄露窗口短),但需要客户端正确处理竞态。
- CAS 存储确保多实例部署中只有一个实例能成功使用某个刷新令牌。
后果
- 凭据存储需要支持 CAS 操作(
IIntegrationCredentialStore的实现需要原子性)。 - 连接器在并发场景下需要优雅处理令牌失效——刷新失败时回退到重新授权流程。
- Jira Cloud Provider 的稳定性标记为
Experimental,直到多租户刷新令牌竞态场景完成验证。 - 首期不含写操作降低了安全风险,但也限制了可用场景。