系列:《让 AI 替你办银行业务:面向 MCP Connector 的身份认证与授权设计》 规范基线:OAuth 2.1 draft-ietf-oauth-v2-1-13;RFC 7009;RFC 7662;OpenID Shared Signals Framework 1.0 与 CAEP 1.0(Final,2025);MCP 2026-07-28 撰写日期:2026-10-23
0. 授权是一个有生命的对象
很多团队把 OAuth 授权当成一次性事件:用户点同意,拿到 token,结束。对 AI connector,这样理解是危险的。用户在某个周末下午授权了 Claude,之后可能几个月都想不起来这件事,而 AI 平台会持续替他刷新 token、调用工具。
所以我们要把**授权(grant)**当作一个有完整生命周期的业务对象来管理:它被建立、被使用、被续期、被扩大或缩小、被暂停、被撤销、最终过期。每一个状态变化都要能被用户看见,并且能实时影响每一次工具调用。
1. 授权的状态机
#mermaid-svg-3huDZNWpgW9xm3Oa{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3huDZNWpgW9xm3Oa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3huDZNWpgW9xm3Oa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3huDZNWpgW9xm3Oa .error-icon{fill:#552222;}#mermaid-svg-3huDZNWpgW9xm3Oa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3huDZNWpgW9xm3Oa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3huDZNWpgW9xm3Oa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3huDZNWpgW9xm3Oa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3huDZNWpgW9xm3Oa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3huDZNWpgW9xm3Oa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3huDZNWpgW9xm3Oa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3huDZNWpgW9xm3Oa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3huDZNWpgW9xm3Oa .marker.cross{stroke:#333333;}#mermaid-svg-3huDZNWpgW9xm3Oa svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3huDZNWpgW9xm3Oa p{margin:0;}#mermaid-svg-3huDZNWpgW9xm3Oa defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-3huDZNWpgW9xm3Oa g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-3huDZNWpgW9xm3Oa g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-3huDZNWpgW9xm3Oa g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-3huDZNWpgW9xm3Oa g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-3huDZNWpgW9xm3Oa g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-3huDZNWpgW9xm3Oa .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-3huDZNWpgW9xm3Oa .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-3huDZNWpgW9xm3Oa .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-3huDZNWpgW9xm3Oa .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-3huDZNWpgW9xm3Oa .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-3huDZNWpgW9xm3Oa .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-3huDZNWpgW9xm3Oa .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-3huDZNWpgW9xm3Oa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3huDZNWpgW9xm3Oa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3huDZNWpgW9xm3Oa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3huDZNWpgW9xm3Oa .edgeLabel .label text{fill:#333;}#mermaid-svg-3huDZNWpgW9xm3Oa .label div .edgeLabel{color:#333;}#mermaid-svg-3huDZNWpgW9xm3Oa .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-3huDZNWpgW9xm3Oa .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-3huDZNWpgW9xm3Oa .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-3huDZNWpgW9xm3Oa .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-3huDZNWpgW9xm3Oa .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-3huDZNWpgW9xm3Oa .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3huDZNWpgW9xm3Oa .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3huDZNWpgW9xm3Oa #statediagram-barbEnd{fill:#333333;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3huDZNWpgW9xm3Oa .cluster-label,#mermaid-svg-3huDZNWpgW9xm3Oa .nodeLabel{color:#131300;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-3huDZNWpgW9xm3Oa .note-edge{stroke-dasharray:5;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-note text{fill:black;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram-note .nodeLabel{color:black;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagram .edgeLabel{color:red;}#mermaid-svg-3huDZNWpgW9xm3Oa #dependencyStart,#mermaid-svg-3huDZNWpgW9xm3Oa #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-3huDZNWpgW9xm3Oa .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3huDZNWpgW9xm3Oa :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
用户在授权页强认证并同意
用户在 App 缩小范围(移除账户、调低额度)
用户暂停 / 风控暂停
用户在 App 内强认证后恢复
用户撤销 / 风控撤销 / 客户端下线 / 账户事件
达到重新认证期限
Active
Suspended
Revoked
Expired
几个设计要点:
- 增量授权不是新 grant,而是同一 grant 的扩展(需重新同意),这样授权管理中心里一个 AI 连接只占一行;
- 缩小范围不需要重新走 OAuth:用户在 App 中移除账户或调低额度,授权登记册即时更新,经由 Token Exchange(第 6 篇)在下一次调用时生效;
- 暂停与撤销分开:暂停可恢复,适合「我出国这两周先停掉」;撤销不可逆,需要重新授权;
- 到期即失效:重新认证期限(第 4 篇建议只读 ≤ 90 天、含起草权限 ≤ 30 天)到了就进入 Expired,AI 客户端刷新时得到 invalid_grant,引导用户重新连接。
2. 各类凭证与句柄的生命周期
| 授权(grant) | 30–90 天 | 银行授权登记册 | 到期、撤销 |
| refresh token | 每次刷新轮换;绝对有效期与 grant 一致 | AI 平台 | 轮换、重用检测、grant 撤销 |
| access token(外部) | 5–15 分钟(第 7 篇) | AI 平台 | 过期;MCP server 实时检查 grant 状态 |
| 内部 token | ≤ 5 分钟 | MCP server 缓存 | 过期;grant 撤销时清除缓存 |
| 支付草稿 | 15 分钟 | 银行 | 签核、拒绝、撤回、过期 |
| MRTR requestState | 15 分钟 | 经客户端往返 | HMAC 过期 |
2.1 refresh token 轮换与重用检测
对公共客户端,OAuth 2.1 和 MCP 都要求 refresh token 要么做持有者约束,要么轮换。轮换的真正价值在于重用检测:
授权服务器
攻击者(偷到 RT1)
AI 平台(合法客户端)
授权服务器
攻击者(偷到 RT1)
AI 平台(合法客户端)
#mermaid-svg-1M4Rjf8q7aMn8OgH{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1M4Rjf8q7aMn8OgH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1M4Rjf8q7aMn8OgH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1M4Rjf8q7aMn8OgH .error-icon{fill:#552222;}#mermaid-svg-1M4Rjf8q7aMn8OgH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1M4Rjf8q7aMn8OgH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1M4Rjf8q7aMn8OgH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1M4Rjf8q7aMn8OgH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1M4Rjf8q7aMn8OgH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1M4Rjf8q7aMn8OgH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1M4Rjf8q7aMn8OgH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1M4Rjf8q7aMn8OgH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1M4Rjf8q7aMn8OgH .marker.cross{stroke:#333333;}#mermaid-svg-1M4Rjf8q7aMn8OgH svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1M4Rjf8q7aMn8OgH p{margin:0;}#mermaid-svg-1M4Rjf8q7aMn8OgH .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-1M4Rjf8q7aMn8OgH text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-1M4Rjf8q7aMn8OgH .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-1M4Rjf8q7aMn8OgH .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-1M4Rjf8q7aMn8OgH .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-1M4Rjf8q7aMn8OgH .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-1M4Rjf8q7aMn8OgH #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-1M4Rjf8q7aMn8OgH .sequenceNumber{fill:white;}#mermaid-svg-1M4Rjf8q7aMn8OgH #sequencenumber{fill:#333;}#mermaid-svg-1M4Rjf8q7aMn8OgH #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-1M4Rjf8q7aMn8OgH .messageText{fill:#333;stroke:none;}#mermaid-svg-1M4Rjf8q7aMn8OgH .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-1M4Rjf8q7aMn8OgH .labelText,#mermaid-svg-1M4Rjf8q7aMn8OgH .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-1M4Rjf8q7aMn8OgH .loopText,#mermaid-svg-1M4Rjf8q7aMn8OgH .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-1M4Rjf8q7aMn8OgH .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-1M4Rjf8q7aMn8OgH .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-1M4Rjf8q7aMn8OgH .noteText,#mermaid-svg-1M4Rjf8q7aMn8OgH .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-1M4Rjf8q7aMn8OgH .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-1M4Rjf8q7aMn8OgH .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-1M4Rjf8q7aMn8OgH .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-1M4Rjf8q7aMn8OgH .actorPopupMenu{position:absolute;}#mermaid-svg-1M4Rjf8q7aMn8OgH .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-1M4Rjf8q7aMn8OgH .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-1M4Rjf8q7aMn8OgH .actor-man circle,#mermaid-svg-1M4Rjf8q7aMn8OgH line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-1M4Rjf8q7aMn8OgH :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
refresh_token=RT1
1
AT2 + RT2(RT1 作废)
2
refresh_token=RT1
3
RT1 已被使用过 → 判定泄露
4
撤销整个 grant(RT2 一并失效)
5
400 invalid_grant
6
refresh_token=RT2
7
400 invalid_grant → 客户端引导用户重新连接
8
触发风控事件,推送 App 通知
9
实现细节:
- 按 grant 维护 refresh token 家族,任何一个旧 token 被重用,整个家族作废;
- 给并发刷新留一个很短的宽限窗口(例如 2–5 秒内允许前一个 RT 再用一次并返回相同结果),否则客户端的并发刷新会被误判为泄露;
- 失效时一律返回 invalid_grant。Claude 文档特别要求这一点:返回 invalid_request 或自定义错误码,可能让客户端反复重试而不是引导用户重新授权;
- 轮换时,新 refresh token 必须和使旧 token 作废的是同一个响应。
3. 撤销:四种来源,一条传播链
3.1 撤销从哪里来
| 用户 | 在 App 授权管理中心点「撤销」 | 单个 grant |
| 银行风控 | refresh token 重用、异常调用模式 | 单个 grant,或该用户的全部 AI grant |
| 账户事件 | 设备重新绑定、密码重置、卡挂失、被标记为疑似受骗、销户 | 该用户的全部 AI grant |
| 客户端级 | AI 平台发生安全事件 | 该 client_id 的全部 grant(一键下线) |
账户事件联动是最容易漏掉的一项。用户刚刚因为手机被盗重新绑定了设备,攻击者却仍可以通过之前建立的 AI 授权读取账户——这显然不合理。建议:设备重新绑定、疑似欺诈标记这两类事件,自动撤销该用户的全部 AI 授权。
3.2 AI 平台侧的「断开连接」
用户在 Claude 里删除 connector,Claude 是否会调用银行的 RFC 7009 撤销端点?撰写时 Claude 的 connector 文档没有说明。银行不能依赖 AI 平台通知撤销:
- 授权登记册中的 grant 仍然有效,直到用户在 App 中撤销或到期;
- 授权管理中心要显示「最后使用时间」,长时间未使用的授权在 App 中提醒用户清理;
- 长期未使用的 grant 可以由银行自动暂停。
3.3 传播:从撤销到下一次调用被拒
AI 客户端
内部 STS
MCP server
事件总线(SSF / CAEP)
授权服务器 / 授权登记册
手机银行 App
AI 客户端
内部 STS
MCP server
事件总线(SSF / CAEP)
授权服务器 / 授权登记册
手机银行 App
#mermaid-svg-kK4LfeqNahx5x1J1{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kK4LfeqNahx5x1J1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kK4LfeqNahx5x1J1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kK4LfeqNahx5x1J1 .error-icon{fill:#552222;}#mermaid-svg-kK4LfeqNahx5x1J1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kK4LfeqNahx5x1J1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kK4LfeqNahx5x1J1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kK4LfeqNahx5x1J1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kK4LfeqNahx5x1J1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kK4LfeqNahx5x1J1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kK4LfeqNahx5x1J1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kK4LfeqNahx5x1J1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kK4LfeqNahx5x1J1 .marker.cross{stroke:#333333;}#mermaid-svg-kK4LfeqNahx5x1J1 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kK4LfeqNahx5x1J1 p{margin:0;}#mermaid-svg-kK4LfeqNahx5x1J1 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-kK4LfeqNahx5x1J1 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-kK4LfeqNahx5x1J1 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-kK4LfeqNahx5x1J1 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-kK4LfeqNahx5x1J1 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-kK4LfeqNahx5x1J1 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-kK4LfeqNahx5x1J1 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-kK4LfeqNahx5x1J1 .sequenceNumber{fill:white;}#mermaid-svg-kK4LfeqNahx5x1J1 #sequencenumber{fill:#333;}#mermaid-svg-kK4LfeqNahx5x1J1 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-kK4LfeqNahx5x1J1 .messageText{fill:#333;stroke:none;}#mermaid-svg-kK4LfeqNahx5x1J1 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-kK4LfeqNahx5x1J1 .labelText,#mermaid-svg-kK4LfeqNahx5x1J1 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-kK4LfeqNahx5x1J1 .loopText,#mermaid-svg-kK4LfeqNahx5x1J1 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-kK4LfeqNahx5x1J1 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-kK4LfeqNahx5x1J1 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-kK4LfeqNahx5x1J1 .noteText,#mermaid-svg-kK4LfeqNahx5x1J1 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-kK4LfeqNahx5x1J1 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-kK4LfeqNahx5x1J1 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-kK4LfeqNahx5x1J1 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-kK4LfeqNahx5x1J1 .actorPopupMenu{position:absolute;}#mermaid-svg-kK4LfeqNahx5x1J1 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-kK4LfeqNahx5x1J1 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-kK4LfeqNahx5x1J1 .actor-man circle,#mermaid-svg-kK4LfeqNahx5x1J1 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-kK4LfeqNahx5x1J1 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
用户
撤销「Claude」的授权
1
强认证后提交撤销
2
grant 状态 → Revoked;作废 refresh token 家族
3
发布事件(session-revoked,subject = grant_id)
4
推送
5
本地撤销表加入 grant_id;清除内部 token 缓存
6
推送
7
拒绝该 grant 的后续交换
8
tools/call(携带仍未过期的 access token)
9
401 invalid_token "authorization revoked"
10
refresh
11
400 invalid_grant
12
「已撤销。Claude 将无法再访问你的账户。」
13
用户
关键在第 7–11 步:access token 还没过期,但下一次调用已经被拒绝。 这依赖 MCP server 在每个请求中检查 grant 状态,而不是只校验 JWT 签名和 exp。示例 bankAuth 中间件:
if (!isClientEnabled(auth.clientId)) {
audit({ action: 'authn', outcome: 'denied', reason: 'client_disabled' }, auth);
return challenge(res, 401, 'invalid_token', 'client disabled by bank');
}
if (!isGrantActive(extra.grantId)) {
audit({ action: 'authn', outcome: 'denied', reason: 'grant_revoked' }, auth);
return challenge(res, 401, 'invalid_token', 'authorization revoked');
}
3.4 JWT 自校验还是内省?
| JWT 自校验(RFC 9068) | 无需调用 AS,延迟低 | 撤销只能靠短有效期或额外的撤销表 |
| 内省(RFC 7662) | 每次都拿到实时状态 | 每次调用都依赖 AS,AS 成为关键路径 |
| JWT + 事件驱动的撤销表(推荐) | 低延迟,撤销秒级生效 | 需要事件基础设施;事件丢失时依赖兜底 |
推荐方案的兜底:MCP server 本地撤销表同时按 TTL(例如 60 秒)定期从授权登记册拉取增量,事件丢失时最多延迟一个 TTL。
事件标准:OpenID Foundation 的 Shared Signals Framework 1.0 与 CAEP 1.0 已于 2025 年成为 Final 规范。SSF 定义安全事件令牌(SET)的传输方式,CAEP 定义会话撤销、凭证变更等事件类型。银行内部使用 SSF/CAEP 的好处是:同一套事件既能驱动 MCP server,也能驱动其他依赖同一身份体系的系统。
4. 用户授权管理中心
授权管理中心是这套设计里用户唯一能看见、能控制 AI 授权的地方,必须放在银行自己的 App 和网银里,而不是 AI 平台上。
4.1 信息架构
#mermaid-svg-AFCl5o6ZuJ17W15j{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AFCl5o6ZuJ17W15j .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AFCl5o6ZuJ17W15j .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AFCl5o6ZuJ17W15j .error-icon{fill:#552222;}#mermaid-svg-AFCl5o6ZuJ17W15j .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AFCl5o6ZuJ17W15j .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AFCl5o6ZuJ17W15j .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AFCl5o6ZuJ17W15j .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AFCl5o6ZuJ17W15j .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AFCl5o6ZuJ17W15j .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AFCl5o6ZuJ17W15j .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AFCl5o6ZuJ17W15j .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AFCl5o6ZuJ17W15j .marker.cross{stroke:#333333;}#mermaid-svg-AFCl5o6ZuJ17W15j svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AFCl5o6ZuJ17W15j p{margin:0;}#mermaid-svg-AFCl5o6ZuJ17W15j .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-AFCl5o6ZuJ17W15j .cluster-label text{fill:#333;}#mermaid-svg-AFCl5o6ZuJ17W15j .cluster-label span{color:#333;}#mermaid-svg-AFCl5o6ZuJ17W15j .cluster-label span p{background-color:transparent;}#mermaid-svg-AFCl5o6ZuJ17W15j .label text,#mermaid-svg-AFCl5o6ZuJ17W15j span{fill:#333;color:#333;}#mermaid-svg-AFCl5o6ZuJ17W15j .node rect,#mermaid-svg-AFCl5o6ZuJ17W15j .node circle,#mermaid-svg-AFCl5o6ZuJ17W15j .node ellipse,#mermaid-svg-AFCl5o6ZuJ17W15j .node polygon,#mermaid-svg-AFCl5o6ZuJ17W15j .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AFCl5o6ZuJ17W15j .rough-node .label text,#mermaid-svg-AFCl5o6ZuJ17W15j .node .label text,#mermaid-svg-AFCl5o6ZuJ17W15j .image-shape .label,#mermaid-svg-AFCl5o6ZuJ17W15j .icon-shape .label{text-anchor:middle;}#mermaid-svg-AFCl5o6ZuJ17W15j .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AFCl5o6ZuJ17W15j .rough-node .label,#mermaid-svg-AFCl5o6ZuJ17W15j .node .label,#mermaid-svg-AFCl5o6ZuJ17W15j .image-shape .label,#mermaid-svg-AFCl5o6ZuJ17W15j .icon-shape .label{text-align:center;}#mermaid-svg-AFCl5o6ZuJ17W15j .node.clickable{cursor:pointer;}#mermaid-svg-AFCl5o6ZuJ17W15j .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AFCl5o6ZuJ17W15j .arrowheadPath{fill:#333333;}#mermaid-svg-AFCl5o6ZuJ17W15j .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AFCl5o6ZuJ17W15j .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AFCl5o6ZuJ17W15j .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AFCl5o6ZuJ17W15j .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AFCl5o6ZuJ17W15j .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AFCl5o6ZuJ17W15j .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AFCl5o6ZuJ17W15j .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AFCl5o6ZuJ17W15j .cluster text{fill:#333;}#mermaid-svg-AFCl5o6ZuJ17W15j .cluster span{color:#333;}#mermaid-svg-AFCl5o6ZuJ17W15j div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AFCl5o6ZuJ17W15j .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AFCl5o6ZuJ17W15j rect.text{fill:none;stroke-width:0;}#mermaid-svg-AFCl5o6ZuJ17W15j .icon-shape,#mermaid-svg-AFCl5o6ZuJ17W15j .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AFCl5o6ZuJ17W15j .icon-shape p,#mermaid-svg-AFCl5o6ZuJ17W15j .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AFCl5o6ZuJ17W15j .icon-shape .label rect,#mermaid-svg-AFCl5o6ZuJ17W15j .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AFCl5o6ZuJ17W15j .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AFCl5o6ZuJ17W15j .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AFCl5o6ZuJ17W15j :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
AI 授权管理
已连接的 AI 服务
总开关:暂停所有 AI 连接
授权变更记录
Claude(claude.ai)· 已验证
连接时间 · 认证方式 · 到期日
可以做:查看 2 个账户的余额与交易起草转账(需你在 App 签核)
起草额度:已用 HK$4,000 / 合共 HK$8,000每笔上限 HK$5,000 · 至 11 月 22 日
最近活动:今天 14:02 查询交易 · 13:58 起草转账(已签核)
操作
移除账户
调低额度
暂停
撤销
4.2 设计原则
4.3 通知
| 新建 AI 授权 | App 推送(立即) |
| 授权范围扩大 | App 推送(立即) |
| AI 起草了一笔付款 | App 推送(即签核请求本身) |
| 风控暂停或撤销 | App 推送 + 短信 |
| 授权即将到期 | App 内提醒(提前 7 天) |
| 长期未使用 | App 内提醒(例如 30 天未用) |
5. 授权登记册的数据模型
{
"grant_id": "grt_8Kd2…",
"status": "active",
"cif": "CIF0012345678",
"sub_pairwise": "pw_4f9c1e…",
"client_id": "examplebank-claude-hosted",
"client_display": { "name": "Claude", "domain": "claude.ai", "verified": true },
"created_at": "2026-10-23T05:58:00Z",
"auth_context": { "acr": "urn:examplebank:acr:bound-device", "amr": ["hwk", "face"], "device_id": "dev_…" },
"scopes": ["accounts:read", "transactions:read", "payments:draft"],
"accounts": ["acc_7Hq2", "acc_9Lm4"],
"authorization_details": [{ "type": "https://examplebank.hk/rar/payment-draft/v1", "…": "…" }],
"reauth_due_at": "2026-11-22T05:58:00Z",
"last_used_at": "2026-10-23T06:02:11Z",
"refresh_family_id": "rtf_…",
"history": [
{ "at": "2026-10-23T05:58:00Z", "event": "created", "by": "user" },
{ "at": "2026-10-23T06:00:30Z", "event": "scope_expanded", "by": "user", "added": ["payments:draft"] }
]
}
6. 到期与续期体验
重新认证期限到了,授权进入 Expired。用户在 AI 里下一次提问时,体验会是这样:
几个细节:
- 提前提醒:到期前 7 天在 App 内提醒,用户可以在 App 内直接续期(强认证后延长期限),避免在 AI 对话中途被打断;
- 续期不扩大范围:续期只延长时间,扩大权限仍走增量授权;
- 起草额度重新计算:新 grant 的累计额度从零开始,旧 grant 下未签核的草稿随旧 grant 失效。
7. 失败模式
| 撤销事件丢失 | 撤销后仍可调用,直到 access token 过期 | 本地撤销表定期全量或增量同步(≤ 60 秒);access token 本身短期 |
| 授权登记册不可用 | MCP server 无法确认 grant 状态 | 闭合:拒绝请求,而不是放行;对只读请求可以容忍短时缓存,对起草请求一律实时确认 |
| 客户端并发刷新 | 被误判为 refresh token 重用,grant 被撤销 | 短宽限窗口;同一宽限窗口内返回相同结果 |
| 时钟漂移 | token 过早失效或过晚失效 | 统一时间源;校验时留 30 秒容差 |
| 用户在多个设备上操作授权管理中心 | 状态冲突 | 以授权登记册为唯一事实来源,每次操作带版本号 |
| AI 平台长期不调用 | 授权一直挂着,用户已忘记 | 长期未用提醒;超过阈值自动暂停 |
8. 撤销时与用户和 AI 的沟通
撤销不只是技术动作,还要让各方得到清楚的反馈:
- 对用户:App 中立即显示「已撤销,Claude 将无法再访问你的账户」;若有未签核的草稿,一并列出并标为作废;
- 对 AI 客户端:MCP server 返回 401 invalid_token,error_description 写明「authorization revoked」,客户端据此提示用户,而不是反复重试;
- 对风控与客服:撤销事件带上来源(用户、风控、账户事件、客户端下线),客服处理投诉时可以直接查到。
风控撤销的情形还要考虑通知措辞:如果是疑似欺诈导致的撤销,通知中不应暴露具体的风控规则,但要告诉用户如何联系银行。
9. 运营指标
| 撤销到 MCP server 拒绝的延迟(P99) | ≤ 5 秒(事件路径),≤ 60 秒(兜底) |
| 客户端一键下线演练 | 每季度一次,全量生效 ≤ 1 分钟 |
| refresh token 重用事件 | 每一起都进入人工复核 |
| 长期未用授权占比 | 持续下降(说明清理提醒有效) |
| 用户撤销率、撤销原因 | 产品与风控的共同输入 |
给银行的设计决策清单
参考资料
- IETF, draft-ietf-oauth-v2-1-13 §4.3(Refresh Token Grant;refresh token 轮换与持有者约束).
- IETF, RFC 7009 OAuth 2.0 Token Revocation;RFC 7662 OAuth 2.0 Token Introspection;RFC 9068.
- OpenID Foundation, Shared Signals Framework 1.0(Final). https://openid.net/specs/openid-sharedsignals-framework-1_0-final.html
- OpenID Foundation, OpenID Continuous Access Evaluation Profile 1.0(Final). https://openid.net/specs/openid-caep-1_0-final.html
- Model Context Protocol Specification 2026-07-28, Authorization — Refresh Tokens;Security Considerations — Token Theft. https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization
- Anthropic, Authentication for connectors — Token refresh. https://claude.com/docs/connectors/building/authentication
- HKMA, “E-Banking Security ABC”(附件,2025-04-11).
网硕互联帮助中心




评论前必须登录!
注册