23

研究 OAuth2.0 我终于找到了这两个参考: RFC6749 section 2.3 , RFC6749 section 10.1

如我错了请纠正我:

可以使用未注册的客户端,但您必须自己管理它们,存在安全风险。

  • 我应该如何管理它们?

一些更具体的问题:

  1. 根据定义,本机应用程序(确实是公共客户端)无法安全地存储其凭据(client_id + secret)。是未注册的客户吗?如果我无法使用秘密验证/验证它,我还应该怎么做?
  2. 客户端注册≠端点注册:首先是关于注册Client Credentials(client_id + secret);第二个关于注册客户端重定向端点。重定向端点注册是否足以授予客户端的真实性?
  3. 客户端凭据授予是否使用相同的凭据 ( client_id + secret) 进行客户端注册?

我认为您可以通过解释本段(RFC6749 第 10.1 节)的含义来回答我。

请给我一些关于如何实现授权服务器和资源服务器之间的交互的参考和实例。

谢谢

4

1 回答 1

37

tl;博士:

  1. 本机客户端无法使用client_id和进行身份验证client_secret。如果您需要对客户端进行身份验证,则必须实施不将共享机密委托给客户端的身份验证方案(或让最终用户参与客户端身份验证讨论)。根据您的应用程序的安全模型,您可能不需要对客户端进行身份验证。
  2. 重定向端点通常不足以对客户端进行身份验证(尽管存在例外)。
  3. “客户端凭据”授权类型可以使用授权服务器支持的任何客户端身份验证机制,包括在客户端注册时给出的凭据。

正如我所读的那样,要点是您可以信任机密客户的client_id(阅读:“用户名”)和client_secret(阅读:“密码”)来使用您的服务对他们进行身份验证。第三方应用程序不可能使用该客户端的凭据来代表自己,因为它们被合理地假设为安全地存储在远离窥探的地方。

然而,公共客户端无法做出这样的保证——无论是基于浏览器的应用程序还是本机桌面应用程序,客户端的 id 和秘密都分发给整个世界。可以合理地假设此类应用程序最终将落入熟练的开发人员和黑客手中,他们可以深入挖掘客户端并提取 id 和秘密。出于这个原因,第 10.1 节明确指出:

The authorization server MUST NOT issue client passwords or other
client credentials to native application or user-agent-based
application clients for the purpose of client authentication.

好的。因此公共客户端无法通过密码进行身份验证。不过……</p>

The authorization server MAY issue a client password or other
credentials for a specific installation of a native application
client on a specific device.

此异常有效,因为它将客户端的身份验证绑定到特定设备,这意味着即使有人离开了客户端的秘密,他们也无法重用它。然而,在这个例外中隐含的是,“特定设备上的特定安装”必须是唯一可识别的、难以欺骗的,并且是该客户端身份验证过程的组成部分。

并非每个本机应用程序都能满足这些标准,而基于浏览器的应用程序当然不能,因为在它运行的环境中没有唯一可识别或难以欺骗的东西。这导致了几个选项——您可以将客户端视为未经身份验证,或者您可以提出更合适的身份验证机制。

身份验证舞蹈的关键是共享秘密——只有授权服务器和身份验证客户端知道的东西。 对于公共客户端,客户端本身没有什么是秘密的。 值得庆幸的是,有很多选择,而且我不只是在谈论 RFID 密钥卡和生物识别技术(尽管这些是完全可以接受的)。

作为一个思想实验,让我们考虑一个基于浏览器的客户端。我们可以合理地假设一些事情:它在浏览器中运行,它从特定域提供服务,并且该域由客户端的作者控制。身份验证服务器应该已经有一个客户端重定向 URI,所以我们已经有了一些东西,但是正如规范所指出的:

A valid redirection URI is not sufficient to verify the client's
identity when asking for resource owner authorization but can be
used to prevent delivering credentials to a counterfeit client
after obtaining resource owner authorization.

所以重定向 URI 是我们应该检查的东西,但不是我们可以信任的东西,很大程度上是因为域可能被欺骗。但是服务器本身不能,所以我们可以尝试向域询问只有客户端域的服务器才知道的东西。最简单的方法是认证服务器需要第二个(“私有”)URI,与客户端在同一个域中,客户端的密钥将在其中托管。当客户端应用程序发出授权请求时,服务器然后“签入”相对于客户端报告的主机名的第二个 URI ,并查找共享密钥(仅应向授权服务器披露)

当然,这不是一个完美的解决方案。它不适用于每个应用程序,很容易出错,并且可能需要大量工作才能实现。存在许多潜在的身份验证机制(包括高度特定的和高度通用的),并且任何不将私有数据委托给客户端应用程序的机制都适用于这个问题空间。

我们的另一个选择是不实施进一步的身份验证,并将客户端视为未经身份验证。这与未注册的客户明显不同,但区别很微妙。未注册客户是身份未知的客户。未经身份验证的客户端是其身份已知但不受信任的客户端。两种类型的客户端的安全含义是相同的:都不应该委托私人数据。然而,授权服务器是否选择同等对待这两种情况似乎是由实施者决定的。例如,一个 API 拒绝所有来自未注册客户端的连接,并向任何注册客户端提供公共只读内容(即使没有验证客户端的身份)。

然而,实用主义可能会胜出——未经身份验证的客户端与 SSL“错误”基本上没有什么不同,当您的浏览器无法验证站点 SSL 证书的真实性时,您偶尔会看到。浏览器将立即拒绝继续并准确报告原因,但允许用户通过保证服务器的身份自行承担风险。类似的工作流程可能对许多 OAuth2 应用程序有意义。

为什么验证客户的身份很重要呢?如果不这样做,信任链就会中断。您的应用程序的用户信任您的应用程序。授权工作流确定您的用户也信任客户端,因此您的应用程序应该信任客户端。在不验证客户端身份的情况下,另一个客户端可以出现并承担受信任客户端的角色,并拥有其所有安全权限。有关客户端身份验证的所有内容都有助于防止违反信任。

希望这有帮助!

[1]:服务器入侵,即您的应用程序的源代码落入恶意手中,这是一个例外,并且针对这种情况内置了其他保护措施。话虽如此,规范还特别指出简单的用户名/密码组合不是最安全的选择:

The authorization server is encouraged to consider stronger
authentication means than a client password.
于 2013-02-03T05:19:24.747 回答