04 — 3D Secure 认证(两条路径)
银行有时要求买家「再证明一次你是你」(3D Secure 强认证)。在 agent 流程里,这一步谁来弹、怎么弹、结果怎么回填?ACP 给了两条路。源头:
rfcs/rfc.agentic_checkout.md(内联)与rfcs/rfc.delegate_authentication.md(独立 API)。
4.1 背景:3DS 是什么,为什么是 agent 的痛点
3D Secure 2(3DS2)是发卡行对一笔交易做的额外验证:有时无感(frictionless)——风控通过就放行;有时要挑战(challenge)——弹个窗让用户输 OTP/做生物识别。问题是:agent 跑在一个不一定有完整浏览器/UI 的环境里,这个「弹窗」怎么处理?这正是 03 章 interventions 协商里 3ds 那一项的现实落地。
4.2 路径一:checkout 内联认证
最轻的方式——认证嵌在 checkout 主线里(rfcs/rfc.agentic_checkout.md:158-164):
agent → POST /complete(不带 authentication_result)
◀── status: authentication_required
+ authentication_metadata(做认证要的信息)
agent 用 metadata 做 3DS 认证(无论成败)
agent → POST /complete(这次带上 authentication_result)
◀── status: completed + order
硬规则:
- 商家在需要认证时必须把
session.status置为authentication_required,且响应必须含authentication_metadata(rfcs/rfc.agentic_checkout.md:159、校验:339)。 - 处于该状态时,agent 必须做认证并把
authentication_result带回 complete——无论认证成败都要带(:160)。 - 若 agent 在该状态下不带
authentication_result就调 complete → 商家必须回 4XX,且type: invalid_request、code: requires_3ds、param: $.authentication_result(:162-164,错误实例:717-724)。
两个关键数据结构(rfcs/rfc.agentic_checkout.md:221-226):
AuthenticationMetadata:acquirer_details、directory_server(amex/mastercard/visa)、可选flow_preference(challenge/frictionless)。AuthenticationResult:outcome+outcome_details,后者含three_ds_cryptogram、electronic_commerce_indicator(ECI)、transaction_id、version——这些就是认证产出的、要随授权一起送给发卡行的「凭据」。complete 请求实例见:573-612。
注意区分两个相似的错误码(rfcs/rfc.agentic_checkout.md:200-201):requires_3ds 是「该带 authentication_result 没带」;intervention_required 是「这单需要某种 agent 根本不支持的介入」(由 03 章的能力协商决定)。别混。
4.3 路径二:独立的 delegate_authentication API
当认证逻辑复杂、需要 agent 直接和认证提供方对话(而不绕经商家)时,用这套独立 API(rfcs/rfc.delegate_authentication.md)。它的范围很窄但很明确:只做 3DS2、只做浏览器渠道、只做原生集成(非重定向)(:18-21)。
三步生命周期,会话化(返回 authentication_session_id,后续放进 URL path,rfcs/rfc.delegate_authentication.md:36):
① POST /delegate_authentication (建会话:商家+卡+金额)
◀── status: action_required(给 fingerprint 动作)
| pending(不需指纹)
| not_supported(卡未登记 → 可不走 3DS)
│
② POST /delegate_authentication/{id}/authenticate (提交指纹结果,触发认证)
◀── status: authenticated(无感成功)
| action_required(需 challenge)
| attempted / not_authenticated / rejected / ...
│
③ GET /delegate_authentication/{id} (取最终结果)
◀── authentication_result{ cryptogram, ECI, trans_status, ... }
端点与状态枚举见 rfcs/rfc.delegate_authentication.md:97-162。
4.4 浏览器侧的两个动作:fingerprint 与 challenge
这套 API 的「动作」对应 3DS2 协议里两个真实的浏览器交互(rfcs/rfc.delegate_authentication.md:180-199):
- Device Fingerprinting:create 回
action.type: fingerprint时,agent 在隐藏 iframe 里把threeDSMethodDataPOST 到发卡行的three_ds_method_url,让 ACS(发卡行的认证服务器)采集设备指纹;收到通知或 10 秒超 时后,带fingerprint_completion(Y/N/U)调 authenticate。 - Challenge Flow:authenticate 回
action.type: challenge时,agent 把 CReq base64(无 padding)POST 到acs_url,在 iframe/modal 里让用户完成挑战;ACS 把 CRes 回调到 agent 的challenge_notification_url,agent 再GET取结果。
agent 因此要实现回调端点接收异步通知(fingerprint/challenge/可选 RReq,:44-49)。
4.5 一个值得注意的安全约束
认证提供方必须做来源限制——请求只能来自 agent 已验证的基础设施(rfcs/rfc.delegate_authentication.md:227-228)。再加上这套 API 要求 Signature 必须验证(注意:这里 Signature 是 REQUIRED,比 checkout 主线的 RECOMMENDED 更严,:67)。原因显而易见:认证是欺诈攻防的最前线,放任意来源调用等于开后门。
4.6 本章要带走的三句话
- 两条路:内联(会话进
authentication_required,带authentication_result回 complete)与独立 API(create→authenticate→retrieve 三步)。 - 3DS2 的两个真实浏览器动作 = fingerprint(采指纹) 和 challenge(弹挑战);独立 API 把它们映射成
action。 - 认证是攻防最前线:独立 API 把
Signature升级为必须,且强制 agent 基础设施来源限制。