摘要
- OAuth First-Party Applications revision 04 提议由 HTTPS Authorization Challenge Endpoint 返回授权码、要求原生客户端继续收集用户输入,或命令其切换到浏览器。省去重定向并没有省去信任判断,而是把已安装应用、发布者证据、界面与风险路由变成凭据表面的一部分。
auth_session、PKCE 与 DPoP 能把协议连续性约束到客户端实例和密钥,却不能证明二进制确为第一方、用户看见了预期提示、同品牌应用保持一致的安全体验、风险升高时确实发生回退,或受权的外部动作已经完成。
用户始终留在银行应用里。原生界面要求输入一次性验证码,应用把它提交给授权服务器,授权码从后通信道返回。没有浏览器弹出,也没有上下文切换。
但少掉的是一次界面交接,不是信任交接。信任只是从授权服务器控制的网页,移动到了客户端控制的原生表面。
OAuth 2.0 for First-Party Applications revision 04 定义了 Authorization Challenge Endpoint。客户端可把登录提示、签名后的 passkey challenge、MFA code 或部署自定义输入交给它。服务器可发放授权码,以 insufficient_authorization 要求继续收集输入,或用 redirect_to_web 把用户送回浏览器。
该文件是 OAuth 工作组在 IETF stream 中的活跃 Internet-Draft。revision 04 日期为 2026 年 7 月 1 日,将于 2027 年 1 月 2 日失效,目标为 Standards Track。它不是 RFC;现有证据也不证明 IANA 注册已经完成、实现已互通、产品已部署、应用商店覆盖足够、钓鱼风险下降或授权结果成功。
新端点把展示权移给了客户端
传统 authorization-code 流程由授权服务器控制浏览器中输入凭据的页面。新草案允许受信任的原生客户端承担大部分交互。它向 HTTPS 端点 POST 授权参数,也能附带已从用户处收集的信息。端点接受 OAuth 参数和服务器支持的扩展,但有些 Web 参数在原生语境下没有明确意义,处理方式被留在范围之外。
这不是“浏览器安全、原生不安全”的二选一,而是展示权限的迁移。服务器仍判断累计信息是否足以发码;客户端却可能决定提示怎样呈现、哪个原生组件读取输入、错误如何解释、何时调用私有的中间端点。
草案明确不标准化中间请求格式、challenge schema 与步骤顺序,完整互通需要部署 profile。两个系统即便都暴露 authorization_challenge_endpoint,也可能对提示词汇、响应含义、合法步骤与安全暗示有完全不同的理解。
因此审计不能只存 HTTP 状态。应记录应用 build 与安装实例、challenge profile、提示类型、scope、输入类别但不保存秘密值、授权服务器 policy 版本、返回码和下一步指令。授权码证明服务器签发了 grant artifact,却无法还原用户此前看到的画面。
“第一方”是一种关系,不是请求字段
草案把 first-party app 定义为:由与授权服务器相同的实体控制,而且用户也理解它属于同一实体。服务器在继续之前必须核验客户端的 “first-partyness”,但具体核验方法被明确留在规范范围之外。
这是一条诚实的边界。移动平台可提供 OS 或 app-store attestation,服务器也可结合 Attestation-Based Client Authentication 或 Dynamic Client Registration。每份证据却只能回答较窄的问题:哪个平台为哪个软件或密钥作证、哪个注册建立了 client record、哪个 publisher identity 被声明、当时哪项 policy 接受了证据。
企业控制、分发托管、已安装 binary 完整性、客户端持钥与用户的品牌认知不是同一事实。发布者签名正确的应用可能版本过旧或被攻陷;合法 package 也可能显示误导提示;DPoP key 若没有 enrollment 与 instance policy 的支持,也可能属于意外复制的实例;熟悉的品牌表面还能被仿造。
决策收据要把 attestation issuer、freshness、nonce、policy result、publisher、distribution channel 与安装实例分开保存,并与 client_id、auth_session 和授权码区分。“已核验第一方”是依赖若干证据边的结论,不是自证的字符串。
auth_session 是由应用携带的 cookie 式状态
auth_session 是服务器签发给客户端的不透明值,用来把后续请求关联到同一客户端实例。它类似浏览器 cookie,但由原生应用自己保存和提交。任何响应都可能轮换这个值;客户端必须接受替换,在授权码发放后继续保存,并在用户退出应用时丢弃。
服务器必须保证会话唯一;若使用随机串,草案建议至少 256 位熵。它应当把会话绑定到设备,并拒绝来自另一设备的提交。规范没有规定寿命,服务器可因定时、风险或撤销事件而使它失效,客户端不能假定持续时间。
因此连续性是状态机而不是一次字符串相等。审计轨迹应记录 session generation、predecessor、client instance、用户上下文、DPoP key、challenge stage、创建和最后使用时间、轮换原因、退出处理与终态,同时避免把不透明值本身写进普通 analytics。
一个当前有效的 auth_session 仅证明服务器愿意继续某份上下文。它不证明此前每个提示都诚实显示,也不证明同一人完成了每一步,或旧版本应用仍值得信任。遇到 invalid_session,准确结论是延续失败,而不是用户无权,也不是新会话必然不安全。
DPoP 绑定密钥,不绑定发布者和界面
revision 04 建议使用 sender-constrained token,并描述 DPoP 如何贯穿 challenge、code、token 和 resource 交互。若客户端从第一条请求起提交 DPoP proof,服务器可要求后续 challenge 与 token exchange 使用同一公钥,也可把 auth_session 关联到这把 key,并在会话出现时验证私钥持有。
这能关闭重要的 replay 缺口:拿到 session 值或 authorization code 的另一设备,若没有密钥就难以继续。尽管后通信道比浏览器重定向更少暴露 code 与 PKCE verifier,端到端 key binding 仍有价值。
可是 key continuity 不等于 app provenance。DPoP 证明提交者控制对应私钥,并且 proof 符合请求坐标;它不说明是谁批准了 enrollment、哪个 package 渲染屏幕、实例是否持续无害、服务器是否仍认可应用,或用户是否愿意授权这个 scope。
应分别输出 dpop_key_match、app_attestation_accepted、client_registration_active、first_party_policy_passed、prompt_profile_matched 与 user_authorization_satisfied。一个模糊的 “bound client” 会抹掉事故调查最需要的差异。
浏览器回退是安全状态转换
redirect_to_web 表明授权服务器需要重新掌握展示面。它可用于高风险请求、应用不支持的新 authentication method、account recovery 或异常流程。客户端随后在 external user agent 中开始新的 authorization-code flow,服务器还可返回 PAR request_uri。
转换本身有连续性要求。如果最初的原生请求没有 PKCE code_challenge,服务器不得返回 request_uri,否则相当于建立一份没有 PKCE 的 pushed request。浏览器路径还应遵循 RFC 8252 与 RFC 9700 的 native-app 安全实践,并使用 RFC 9207 的 issuer identification 等手段。
风险开关必须有独立收据:记录 policy trigger、risk band、不支持方法或恢复原因,PKCE 是否已建立,issuer 与 request reference,外部浏览器,return URI、state continuity,以及控制权返回后的结果。“打开过浏览器”不证明到达正确服务器;“继续留在原生界面”也不证明无需回退。
客户端若悄悄把 redirect_to_web 变成一次原生重试,就跨越了政策边界。用看似外部的 embedded web view 代替系统浏览器也一样。测试应覆盖从服务器响应、OS browser 选择直到 issuer-bound callback 的完整转换。
多个第一方应用会复制信任决策
草案要求同一服务器支持多个第一方应用时,原生体验必须一致。这不仅是品牌规范。若用户被训练在若干不同样式的原生提示中输入凭据,就更难解释哪一个仿冒面是假的。每套实现还多出 parser、storage path、SDK version、accessibility layer 和失败模式。
共享 SDK 可减少偏差,也形成共同依赖。SDK 的版本、签名与 rollout 都进入授权控制面:它被攻陷时可一致扩散,分叉时又会不一致漂移。“相同体验”应作为安全合同测试,包括提示与来源暗示、秘密输入处理、截屏和辅助功能暴露、回退行为、错误语义、会话存储与 telemetry redaction,而不仅是颜色和排版。
服务器需要一张清单,把每个 client identifier 和 attestation policy 映射到 owning entity、publisher、distribution channel、允许 build、共享 SDK、challenge profile 与退役计划。某个 sibling app 不满足相同控制时,不能仅因同品牌而继承信任。
原生取得授权码仍只是一个坐标
Authorization Challenge Endpoint 最终发放的仍是 authorization code,token endpoint 再产生 access/refresh token。resource server 还可稍后要求 step-up,让客户端携带 acr_values、max_age 和 scope 重新开始 challenge。
每次转换含义不同:code 是短期 grant artifact;PKCE 把它关联到 verifier;DPoP 把 flow 和 token 关联到 key;auth_session 把请求关联到服务器上下文;step-up 参数描述额外认证需要;access token 则在 resource server 的验证规则下表达授权。
它们都不证明业务动作已经发生。资源服务器仍可拒绝、收紧 policy,或接受请求却未完成下游转账;用户也可能关掉应用,payment 可能逆转,credential 可能签发却未安装。最终证据链必须在 OAuth 收据之后另存 resource decision 和现实结果。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
