接续自 OIDC 登录通过 Discourse iOS 应用偶尔在回调时失败并显示 csrf_detected 的讨论:
大家好,
这是关于我之前关于从 iOS 应用内浏览器发起的 OIDC 登录失败的帖子的后续观察。该讨论侧重于由 WKWebView Cookie 隔离引起的确定性 csrf_detected 失败,这些失败现在似乎已得到充分理解和预期。
这个链接的主题是关于操作员清晰度,而不是错误。
观察
在调查一系列 OIDC 登录失败时,我注意到 Discourse 中相同的表面错误:
/auth/oidc/callback → /auth/failure?message=csrf_detected
可能对应于多个根本不同的上游原因,具体取决于 IdP 返回的内容。
仅从应用程序 UI 来看,这些情况是无法区分的。差异只能通过检查“管理”→“日志”→“env / params”来查看。
实践中观察到的示例(Azure / Entra ID)
除了应用内浏览器 Cookie 丢失之外,我还观察到 Entra ID 明确返回结构化错误的那些回调,例如:
用户拒绝同意
error=consent_required
error_description=AADSTS65004: User declined to consent to access the app
用户取消登录
error=access_denied
error_subcode=cancel
在这两种情况下:
- Azure 成功识别了用户
- 用户明确选择不继续(拒绝/取消)
- Discourse 接收到回调
- 流程最终解析为
/auth/failure?message=csrf_detected
从 Discourse 的角度来看,这是正确且安全的行为——状态无法验证或完成——但根本原因与缺少会话 Cookie 非常不同。
对操作员的重要性
如果没有检查日志的 env/params,看到重复的 csrf_detected 失败的管理员可能会合理地假设:
- Cookie 损坏
- SameSite 配置错误
- 移动浏览器问题
- IdP 不稳定
……但实际上,其中一些失败仅仅是用户选择不同意或取消了 Microsoft 的提示。
只有当您已经知道要检查原始日志有效负载时,这种区别才会变得清晰。
建议(仅限文档/UX)
我不是建议对 OmniAuth 或 CSRF 处理进行任何行为更改。
如果文档或故障排除指南明确指出以下内容可能会有所帮助:
csrf_detected可以是多个上游 IdP 结果的最终错误- 包括明确的用户操作,如取消或拒绝同意
- 管理员应检查“管理”→“日志”→“env / params”以区分这些情况
这将使操作员更容易:
- 正确诊断登录失败
- 避免不必要的配置更改
- 并向用户提供准确的指导(“您已取消/拒绝同意”与“您的浏览器阻止了 Cookie”)。
背景
为求清晰:这与链接主题中讨论的已确认的 iOS 应用内浏览器问题是分开的。在这种情况下,IdP 从未达到用户同意的阶段,而在本例中,IdP 会明确报告用户意图。
除非检查日志,否则两者在 UI 级别看起来都很相似。
感谢阅读——发布此内容主要是为了提高文档的清晰度/为在学生众多的环境中运行 OIDC 的其他人提供一个数据点,因为这些情况经常发生。
如果需要,我很乐意提供匿名示例。