本机应用程序的 OAuth 2 - public 和机密客户端类型之间有什么区别?

OAuth 2 for native application - what is difference between public and confidential client types?

我试图为 Web 服务实施 OAuth 2 提供程序,然后在其之上构建本机应用程序。另外,我想为第三方开发者授予 API 的访问权限。

我已经阅读了 OAuth 2 规范,但无法选择正确的流程。我也想验证 CLI 和 GUI 应用程序。

首先,我们有两种客户类型 - public 和机密。当然,GUI 和 CLI 应用程序都将是 public。但这两种类型之间有什么区别?在这种情况下,我需要什么 client_secret 如果我可以通过更改客户端类型获得访问令牌而不需要它?

我试图查看一些 API 流行服务的实现,例如 GitHub。但他们使用 HTTP Basic Auth。不确定这是个好主意。

有什么特别的区别吗?一个比另一个提高了安全性吗?

关于public和保密客户的区别,见http://tutorials.jenkov.com/oauth2/client-types.html,其中说:

A confidential client is an application that is capable of keeping a client password confidential to the world. This client password is assigned to the client app by the authorization server. This password is used to identify the client to the authorization server, to avoid fraud. An example of a confidential client could be a web app, where no one but the administrator can get access to the server, and see the client password.

A public client is an application that is not capable of keeping a client password confidential. For instance, a mobile phone application or a desktop application that has the client password embedded inside it. Such an application could get cracked, and this could reveal the password. The same is true for a JavaScript application running in the users browser. The user could use a JavaScript debugger to look into the application, and see the client password.

机密客户端比 public 客户端更安全,但您可能无法始终使用机密客户端,因为它们 运行 在 (c.q 中的环境受到限制。本机应用程序、浏览器内客户端)。

@HansZ 的回答是一个很好的起点,因为它阐明了 public 和私人客户端应用程序之间的区别:使客户端机密保密的能力。

但它没有回答以下问题:对于哪些用例,我应该使用什么 OAuth2 配置文件?要回答这个关键问题,我们需要更深入地研究这个问题。

对于机密应用程序,客户端机密是带外 (OOB) 提供的,通常通过配置(例如在属性文件中)提供。对于基于浏览器和移动应用程序,实际上没有任何机会执行任何配置,因此,这些被视为 public 应用程序。

到目前为止,还不错。但我不同意这会使此类应用程序无法接受或存储刷新令牌。事实上,SPA 和移动应用程序使用的重定向 URI 通常是 localhost,因此 100% 等同于直接从令牌服务器接收令牌以响应资源所有者密码凭证授予 (ROPC)。

许多作者指出,OAuth2 实际上并不进行身份验证,有时是正确的。事实上,正如 OAuth2 RFC 6749 所述,执行身份验证需要 ROPC 和客户端凭据 (CC) 授权。参见 Section 4.3 and Section 4.4

但是,对于 Authorization CodeImplicit 赠款,该陈述是正确的。但是这些域的​​身份验证实际上是如何工作的?

通常,用户将她的用户名和密码输入到浏览器表单中,该表单被发布到身份验证服务器,身份验证服务器为其域设置 cookie。抱歉,即使在 2019 年,cookie 也是最先进的身份验证技术。为什么?因为 cookie 是浏览器应用程序保持状态的方式。它们没有任何问题,浏览器 cookie 存储相当安全(受域保护,JS 应用程序无法获取“仅 http”cookie,安全要求 TLS/SSL)。 Cookie 只允许在第一次授权请求时显示登录表单。之后,重新使用当前身份(直到会话过期)。

好的,那上面的和ROPC有什么不同呢?不多。区别在于登录表单的来源。在 SPA 中,已知该应用程序来自 TLS/SSL 已验证服务器。所以这与让服务器直接呈现表单完全相同。无论哪种方式,您都通过 TLS/SSL 信任该站点。对于移动应用程序,通过应用程序签名已知表单来自应用程序开发人员(来自 Google Play、Apple Store 等的应用程序已签名)。所以,再次,有一个类似于 TLS/SSL 的信任机制(没有更好,也没有更坏,取决于商店、CA、受信任的根分布等)。

在这两种情况下,都会返回一个令牌,以防止应用程序在每次请求时都必须重新发送密码(这就是 HTTP 基本身份验证不好的原因)。

在这两种情况下,必须加强身份验证服务器以抵御任何面向 Internet 的登录服务器所遭受的攻击。授权服务器没有这个问题那么多,因为它们委托了身份验证。但是,OAuth2 passwordclient_credentials 配置文件都充当事实上的身份验证服务器,因此确实需要严格。

为什么您更喜欢 ROPC 而不是 HTML 表格?非交互式案例(例如 CLI)是常见的用例。大多数 CLI 都可以被认为是机密的,因此应该同时具有 client_idclient_secret。请注意,如果 运行 在共享 OS 实例上,您应该编写 CLI 以从文件中提取客户端机密和密码,或者至少从标准输入中提取,以避免机密和密码出现在处理清单!

本机应用程序和 SPA 是另一个很好的用途,imo,因为这些应用程序需要令牌才能传递给 REST 服务。但是,如果这些应用程序也需要 cookie 进行身份验证,那么您可能希望使用授权代码或隐式流程并将身份验证委托给常规 Web 登录服务器。

同样,如果用户未在与资源服务器相同的域中进行身份验证,您确实需要使用授权代码或隐式授权类型。用户必须如何进行身份验证取决于授权服务器。

如果使用双因素身份验证,事情就会变得棘手。我自己还没有穿过这座特殊的桥。但我见过像 Attlassian 这样的案例,它可以使用 API 密钥来允许访问通常需要除密码之外的第二个因素的帐户。

请注意,即使您在服务器上托管 HTML 登录页面,您也需要注意它不会被浏览器中的 IFRAME 或本机应用程序中的某些 Webview 组件包装(这也许能够设置挂钩以查看您输入的用户名和密码,这就是密码管理器的工作方式,顺便说一句)。但这是属于“登录服务器强化”的另一个主题,但答案都涉及客户端尊重网络安全约定,因此对应用程序有一定程度的信任。

几个最后的想法:

  1. 如果通过任何流类型将刷新令牌安全地传送到应用程序,则它可以安全地存储在 browser/native 本地存储中。浏览器和移动设备可以很好地保护这种存储。当然,它不如仅在内存中存储刷新令牌安全。所以可能不适用于银行应用程序......但是很多应用程序都有很长的会话(数周),这就是它的完成方式。

  2. 不要将客户端机密用于 public 应用。它只会给你一种虚假的安全感。仅当存在安全的 OOB 机制来传递机密并且它被安全存储(例如锁定 OS 权限)时,客户端机密才适用。