使用Google OIDC进行代码流和PKCE

23
经过试错,我发现 Google OIDC 不支持在不提供客户端密钥的情况下使用代码流程(code flow): 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),Code Flow + PKCE 是处理身份验证的推荐方式。有人知道如何使 Google 的 Code Flow 接受 code_challenge 而不是 client_secret 吗?也许可以使用虚拟的 secret?

我现在也遇到了“client_secret”的问题。因此,我在Google上开了一个问题以引起一些关注。对此的任何支持都将受到欢迎。主要问题是accounts.google.com/token端点要求我们为Web客户端发送client_secret。https://issuetracker.google.com/issues/184351769 - Flos
4个回答

17
截至2020年8月,最佳实践文件仍在起草并正在积极更新中-最新版本位于此处:https://datatracker.ietf.org/doc/draft-ietf-oauth-security-topics/。谷歌的OAuth2实现尚未应用PKCE“正在进行”的推荐标准,适用于Web应用程序。谷歌在线文档仍指导SPA使用隐式流程:https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow
PKCE的标准(https://www.rfc-editor.org/rfc/rfc7636)详细说明其作为移动平台上发现的授权代码拦截攻击的缓解措施,并最初建议由原生客户端实施。谷歌针对“移动和桌面应用程序”的文档确实指示开发人员使用PKCE授权代码流。使用Google Android、iOS或Windows Store凭据类型的客户端可能省略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应用程序。


4
荒谬,我简直不敢相信你最后的那段话。但这是真的吗?https://developers.google.com/identity/protocols/oauth2/native-app#step1-code-verifier 上说“Google支持[PKCE]以使安装的应用程序流程更加安全”。但是如果没有客户端密钥,我无法使用PKCE进行Google OIDC。Google强制要求我的客户端有一个密钥,而这个密钥总是会被盗取,参见:https://developer.okta.com/blog/2019/01/22/oauth-api-keys-arent-safe-in-mobile-apps#https-requests-can-be-intercepted-from-mobile-apps。这完全消除了PKCE提供的任何安全优势?请告诉我我错了。 - Heinzlmaen
1
我至少在某种程度上是错误的。在我看来,PKCE仍然是安全的。但是,如果您有多个应用程序针对一个已注册的Google API/应用程序使用不同的流程,我不确定会发生什么。如果您的PKCE应用程序暴露了密钥,其他具有不同流程的应用程序是否仍然安全? - Heinzlmaen
1
在这方面有任何变化吗?我找不到任何其他的说法。 - Robotronx
2
@Heinzlmaen 是的,这就是PKCE的意义所在...“客户端密钥”不被视为机密。无论Google是否强制你提供一个,它都不是最终可信的。虽然这可能会迫使攻击者付出更多的努力...也就是说,如果客户端密钥实际上是错误的,那么尽快发送4xx状态码比经过整个过程直到发现PKCE也是错误的消耗更少的资源。因此,请将其视为快速失败的反滥用要求。 - David Bullock
3
@Ash 对于已安装的应用程序,您可能会通过应用商店等方式'分发应用程序二进制文件',现在任何拥有您二进制文件的一方都可以在他们的反汇编器中看到您的应用程序的'client_secret'和'client_id'。对于网站来说...客户端密钥留在服务器农场上,没有问题。但是,如果一个已安装的应用程序在没有PCKE的情况下执行'授权代码'流程,则存在同一设备上的恶意应用程序拦截'redirect'的风险,然后使用YOUR应用程序的client-id/client-secret交换代码以获取访问令牌。使用PCKE,它还必须证明它是在获取令牌之前启动OAuth请求的那个应用程序。 - David Bullock
显示剩余6条评论

2

我正在使用OpenID Connect授权码,使用pkce而不使用client_secret在Android应用程序中。我使用这个库:https://github.com/openid/AppAuth-Android

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


1
但是你没有使用Google OIDC吗? - Heinzlmaen

2
在我看来,一个好的选择是使用Keycloak作为IDP,然后将Google添加到您的Keycloak实例的委托身份提供者中(然后是Facebook,如果需要的话还可以添加其他idp)。Keycloak可靠地实现了Oauth 2 RFCs中的PKCE流程或任何流程。这意味着您需要一个托管的Keycloak实例。

0
请注意,谷歌在其OIDC配置端点中提到它支持纯文本和S256作为PKCE代码挑战方法。我刚刚在谷歌上使用代码流测试了使用客户端密钥并在相关的授权步骤中传递code_challenge和code_verifier。
以下是我在撰写时的观察:
1. 如OP所述,仍然需要客户端密钥,否则谷歌会抱怨缺少字段。 2. 如果您发送客户端密钥,谷歌支持PKCE流程。更准确地说: - 如果您传递一个代码挑战和有效的代码验证器,那么您将从令牌端点获取您的令牌。 - 如果您将代码挑战和无效的代码验证器传递给令牌端点,则会收到invalid_grant错误。
为了完整起见,这是如果您在使用客户端凭据和无效的代码验证器的代码流中出现的错误消息:
{
  "error": "invalid_grant",
  "error_description": "Invalid code verifier."
}

所以,如果你只是将代码挑战和验证器与客户端密钥一起发送,你可以使用PKCE来提供额外的安全性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接