Google 表示它支持 OAuth 2.0 的 PKCE(请参阅 docs)。然而,Google PKCE 流程需要客户端密钥,这违反了 PKCE 标准,并且当客户端是移动或桌面应用程序时可能存在危险,而这正是我所拥有的。
这似乎是一个长期存在的问题...请参阅 2020 年的 这个 SO 问题。
几个问题:
是的,这就是 PKCE 的要点……“客户端秘密”不被认为是秘密。无论 Google 是否强迫您提供,它最终都不是可信的。
另一个SO答案也表明了这一点:
不保守“客户秘密”是可以的。在 OAuth2 规范中,不保守客户端机密的客户端类型称为“公共客户端”。以下事实可以防止有人恶意获取授权代码,然后获取访问令牌:(1) 客户端需要直接从用户而不是服务获取授权代码 (2) 重定向 URL 已注册客户端 ID/秘密
第三个SO答案建议“客户端密钥对于服务器端应用程序比客户端应用程序重要得多”。
SPA 仍被指示使用 Google 在线文档中的隐式流程:https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow)。
根据我的理解,隐式流程有几个主要缺点:(1)它不支持刷新令牌(参见here),这可能会导致糟糕的用户体验;(2)它已被很大程度上弃用,以支持PKCE(参见此处)。
- 使用 Google PKCE 流程时,将客户端密钥存储在移动或桌面客户端上是否安全?
如果客户端秘密仅由具有 PKCE 的客户端使用,我认为将客户端秘密公开并不是那么有问题。 为了考虑 PKCE 流程,我们应该考虑授权码被盗攻击。恶意应用程序试图在用户身份验证后窃取代码(例如通过 MITM 攻击)。如果我们没有 PKCE 引入的 code_verifier,则恶意用户可以使用窃取的代码、client_id 和机密来获取刷新令牌。通过使用 PKCE 流程,我们可以在有或没有 client_secret 的情况下防止这种情况,因为 IdP 和您的应用程序可以通过 code_challenge/code_verifier 确认同一应用程序是否请求刷新令牌。
有/没有 client_secret 的风险是相同的:恶意用户可能能够从 code_challenge 重现 code_verifier。
您是否了解为什么 Google PKCE 在明显违反标准的情况下需要客户端密钥?
请注意,Android 应用程序不会生成 client_secret。他们可能认为有一个本机客户端可以安全地存储 client_secret。 Google 为每个客户端颁发一个 client_id/secret。他们可能认为开发人员可以控制安全性。但是,我认为这会让那些不太了解的开发人员面临在没有 PKCE 的情况下暴露 client_secret 的风险。