将 Google OIDC 与代码流和 PKCE 结合使用

Posted

技术标签:

【中文标题】将 Google OIDC 与代码流和 PKCE 结合使用【英文标题】:Using Google OIDC with code flow and PKCE 【发布时间】:2020-06-28 16:05:27 【问题描述】:

经过反复试验,在我看来,Google OIDC 在不提供客户端密码的情况下不支持代码流: https://developers.google.com/identity/protocols/oauth2/native-app#exchange-authorization-code

根据 SPA 的最新最佳实践 (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-13),推荐使用代码流 + PKCE 来处理身份验证。是否有人知道使 Google 的代码流接受 code_challenge 而不是 client_secret 所需的任何技巧?也许是一个虚假的秘密?

【问题讨论】:

我现在对“client_secret”也有疑问。所以我在谷歌打开了一个问题来给予它一些关注。欢迎对此提供任何支持。主要问题是 accounts.google.com/token 端点要求我们为 Web 客户端发送 client_secret。 issuetracker.google.com/issues/184351769 【参考方案1】:

恕我直言,一个很好的替代方案是使用 Keycloak 作为 IDP,然后将 Google 添加到您的 Keycloak 实例的委托身份提供者(然后是 Facebook,如果需要,再添加任何其他 idp)。 Keycloak 以可靠的方式实现 PKCE 流或 Oauth 2 RFC 中的任何流。这意味着您需要一个托管的 Keycloak 实例。

【讨论】:

【参考方案2】:

截至 2020 年 8 月,引用的最佳实践文档仍处于草稿阶段,正在积极更新 - 此处为主要修订:https://datatracker.ietf.org/doc/draft-ietf-oauth-security-topics/。 Google 的 OAuth2 实施尚未将 PKCE 的“正在进行中”的建议应用于 Web 应用程序。 SPA 仍被指示使用 Google 在线文档中的隐式流程:https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow)。

PKCE 标准 (https://www.rfc-editor.org/rfc/rfc7636) 详细说明它是为缓解在移动平台上发现的授权代码拦截攻击而开发的,最初建议由本机客户端实施。 Google 的“移动和桌面应用程序”文档确实指导开发人员使用 PKCE 授权代码流程。使用带有 PKCE 的 Google androidios 或 Windows 存储凭据类型的客户端可能会省略 client_secret(请参阅刷新令牌参数表上的注释 - 并由 Cristiano 确认)。

现在人们认识到,PKCE 消除了任何公共客户端存储客户端机密的需要,因此可用于弃用始终存在包含返回访问和重定向 URI 中的身份令牌。 https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead.

IETF 文件草案在第 2.1.1 节中指出,这种认可很可能成为已发布的标准。

希望 Google 将更新其实施,以在最佳做法被接受时取消对 PKCE 令牌请求的 client_secret 要求。与此同时,我们似乎别无选择,只能继续使用隐式流程编写 SPA。

【讨论】:

荒谬,我简直不敢相信你的最后一段话。但这是真的吗?! developers.google.com/identity/protocols/oauth2/… 表示“Google 支持 [PKCE] 以使安装的应用程序流程更加安全”。但是我不能在没有客户端密码的情况下使用 PKCE 进行 Google OIDC。谷歌强迫我对我的客户有一个秘密,并且总是可以被窃取,请参阅:developer.okta.com/blog/2019/01/22/…。完全消除 PKCE 提供的任何安全优势?请告诉我我错了。 我至少部分错了。 PKCE 仍然是安全的 imo。但是我不确定如果您为一个注册的 Google api/应用程序有多个具有不同流程的应用程序会发生什么。如果您的 PKCE 应用程序公开了机密,那么具有其他流的其他应用程序是否仍然安全? 这方面有什么变化吗?我找不到其他可以说的。 @Heinzlmaen 是的,这就是 PKCE 的重点……“客户机密”不被视为机密。无论 Google 是否强迫您提供,它最终都不会被信任。虽然它可能至少会迫使攻击者付出更多努力......也就是说,如果客户端秘密实际上是错误的,那么尽快发送 4xx 状态代码消耗的资源比通过整个游戏直到发现PKCE也是错误的。因此,可以将其视为快速失败的反滥用要求。 @Ash 对于已安装的应用程序,您可能会“分发应用程序二进制文件”(例如,通过应用商店),现在任何拥有您的二进制文件的一方都拥有您的应用程序的“client_secret”和他们的反汇编程序中的“client_id”。对于 websites ...客户端秘密保留在服务器场上,没有问题。但是,在没有 PCKE 的情况下执行“授权代码”流程的已安装应用程序可能会冒着同一设备上的恶意应用程序拦截“重定向”的风险,然后使用您的应用程序的客户端 ID/客户端秘密将代码交换为访问令牌。对于 PCKE,它还必须证明它是在获取令牌之前发起 OAuth 请求的人。【参考方案3】:

好吧,我正在使用带有 pkce 的 openId Connect 授权代码,而没有在使用此库的 Android 应用程序中使用 client_secret:https://github.com/openid/AppAuth-Android。

我只需要确保使用清单中的应用程序包名称设置自定义方案,并使用它在 google 控制台上注册 android 凭据。

【讨论】:

但是您没有使用 Google OIDC?

以上是关于将 Google OIDC 与代码流和 PKCE 结合使用的主要内容,如果未能解决你的问题,请参考以下文章

使用 .Net 5 WebAPI 的 Vue SPA 的正确 OIDC 流程是啥?

调用signinRedirect时的Oidc-client无限循环

如何使用 PKCE 为 React 单页应用程序实现 OAuth2 授权代码授予?

使用“Auth Code Flow + PKCE”时来自令牌端点的 CORS 错误

如何使用 PKCE 登录 Google.Apis.Drive.v3 for .NET?

Azure AD:带有 PKCE 的代码流:没有为应用程序启用 id_token