OAuth2 密码授予与 OpenID 连接

Posted

技术标签:

【中文标题】OAuth2 密码授予与 OpenID 连接【英文标题】:OAuth2 Password Grant vs OpenID Connect 【发布时间】:2018-05-06 23:05:58 【问题描述】:

我一直在广泛阅读有关 OAuth 和 OpenID Connect 的内容,但这个问题专门针对 OAuth2 资源所有者密码授予(又名 OAuth2 资源所有者凭据授予,又名 OAuth2 密码授予)

一些资源(例如 Justin Richer 的“OAuth2 in Action”一书)说不要使用 OAuth2 Resource Owner Password Grant 进行身份验证 - 请参阅书中的第 6.1.3 节。

像下面这样的其他优秀资源都表明我们可以使用 OAuth2 资源所有者密码授权来通过受信任的应用对用户进行基本身份验证

    https://www.oauth.com/oauth2-servers/access-tokens/password-grant/ https://stormpath.com/blog/the-ultimate-guide-to-mobile-api-security https://www.youtube.com/watch?v=FNz0Lupp8HM&index=60&list=PLyUlngzGzkztgTizxM6_zqiw8sRj7vBm0 https://docs.apigee.com/api-services/content/implementing-password-grant-type https://oauth2.thephpleague.com/authorization-server/which-grant/ https://aaronparecki.com/oauth-2-simplified/#others

但是我很难理解为什么我们不应该使用 OAuth2 资源所有者密码授权作为成功身份验证的基本证明?

我对资源所有者密码授予流程的理解是,最终用户将用户名和密码提供给受信任的客户端(我的本机应用程序),然后将其转发到我的 API 的 OAuth 服务器并将其交换为访问令牌(和可选的刷新令牌),它可以用于其余经过身份验证的 API 端点。原生应用不保存用户名/密码,而是依赖短期访问令牌和长期刷新令牌(在过期时获取新的访问令牌)。

为什么我什至需要 OpenID Connect?为什么我不能只使用 OAuth2 资源所有者密码授予作为身份验证机制?

原生应用和 API 都是由同一个人(我)开发的。

欢迎任何解释。谢谢。

【问题讨论】:

您找到问题的答案了吗?我对同样的事情感到困惑。 【参考方案1】:

如果服务器和客户端应用程序都是您的,您可以使用资源所有者密码凭据流来获取访问令牌。

如果服务器是您的,但客户端应用程序不是您的(= 如果客户端应用程序是由第三方供应商开发的),则您的服务器不应允许客户端应用程序使用资源所有者密码凭据流。这是因为资源所有者密码凭据流无法阻止第三方客户端应用程序窃取最终用户的密码。

OpenID Connect 的规范没有描述 OpenID 提供者应该如何验证最终用户的身份。相反,该规范描述了 OpenID 提供者应如何生成 ID 令牌。因为 ID 令牌包含由 OpenID 提供者生成的签名,所以接收 ID 令牌的客户端应用程序可以验证 ID 令牌是否真的由 OpenID 提供者签名。

也就是说,OpenID Connect 是关于如何使最终用户身份验证的结果可验证的规范。它不是关于如何验证最终用户的规范。

【讨论】:

是的,原生应用和API都是我控制和开发的。您是否知道不允许第三方客户端应用程序将资源所有者密码凭证与我的 API 一起使用的方法?他们可能可以通过分析原生应用程序来获取原生应用程序的客户端 ID。我计划保持客户秘密为空/空白。对此有什么想法吗?【参考方案2】:

资源所有者凭据授予比任何其他授予具有更高的风险,并且违背了协议的目的,该协议旨在hide user credentials from the client application

在原生应用程序的情况下 - 你是对的,它可以分析你的应用程序并从中检索消费者密钥。我也可以想象有人创建了一个类似于你的应用程序,并从中获取用户的密码,并在用户没有注意到的情况下执行其他潜在的恶意操作。

我建议您阅读OAuth2 和OpenID Connect 的规范。 为什么不应该使用资源所有者密码授权(来自OAuth2 spec):

资源所有者密码凭据授予类型通常用于 遗留或迁移原因。它降低了存储的总体风险 客户的用户名和密码,但并不消除需要 向客户端公开高权限凭据。

这种资助类型比其他资助类型具有更高的风险,因为 它维护该协议试图避免的密码反模式。 客户端可能滥用密码,或者密码可能 无意中泄露给攻击者(例如,通过日志文件或 客户保存的其他记录)。

另外,因为资源所有者无法控制 授权过程(资源所有者的参与在 它将其凭据交给客户端),客户端可以获得 访问范围比资源所需范围更广的令牌 所有者。授权服务器应考虑范围和 通过此授权类型颁发的访问令牌的生命周期。

授权服务器和客户端应该尽量减少使用这个授权 尽可能键入并使用其他授权类型。

【讨论】:

【参考方案3】:

OAuth 2.0,无论授权类型如何,is not an authentication protocol。

OpenID Connect 是建立在 OAuth 2.0 之上的身份验证协议

这些是一些参考资料(一些来自编写 OAuth 2.0 和/或 OpenID Connect 的人):

http://www.thread-safe.com/2012/01/problem-with-oauth-for-authentication.html https://twitter.com/ve7jtb/status/740650395735871488

https://nat.sakimura.org/2013/07/05/identity-authentication-oauth-openid-connect/

http://ldapwiki.com/wiki/OAuth%202.0%20NOT%20an%20Authentication%20protocol

【讨论】:

感谢您的链接。我阅读了它们,但我仍然不清楚为什么我不应该在我的本机应用程序和我的 API 之间使用 OAuth2 资源所有者密码授权?

以上是关于OAuth2 密码授予与 OpenID 连接的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Spring Oauth2 密码授予中获取访问令牌

OpenID Connect 是不是支持资源所有者密码凭证授予?

OAuth2 密码授予混淆

在不使用cookies的情况下使用授权码授予?

OAuth2 密码授予和基本身份验证

使用 Oauth2/OpenID 连接构建 Web-API