OAuth 2用于本地应用程序 - 公共客户端类型和机密客户端类型有何区别?

26

我正在尝试为Web服务实现OAuth 2提供程序,并在其上构建本地应用程序。同时,我想为第三方开发人员提供API访问权限。

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

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

我试图查看GitHub等流行服务的一些API实现。但它们使用HTTP基本身份验证。不确定这是否是一个好主意。

这两种方法有什么区别吗? 是否有一种方法可以提高安全性?

2个回答

21
关于公开客户端和机密客户端之间的区别,请查看http://tutorials.jenkov.com/oauth2/client-types.html,该网站如下所述:

机密客户端是一种能够将客户密码保密不向外界泄露的应用程序。此客户密码由授权服务器分配给客户端应用程序。该密码用于将客户端标识给授权服务器以避免欺诈。机密客户端的一个例子可以是Web应用程序,在这种情况下只有管理员才能访问服务器并查看客户端密码。

公共客户端是一种无法保持客户端密码保密的应用程序。例如,嵌入了客户端密码的移动电话应用程序或桌面应用程序。这样的应用程序可能会被破解,从而揭示密码。对于在用户浏览器中运行的JavaScript应用程序同样如此。用户可以使用JavaScript调试器查看该应用程序并查看客户端密码。

机密客户端比公共客户端更安全,但由于其运行环境受到限制(即本地应用程序、浏览器内客户端),您可能无法始终使用机密客户端。

谢谢您的回复!是的,但是对于提供者来说有什么区别呢?规范说明我不应该为公共客户端提供刷新令牌。这就是区别吗?此外,我想仅为我的第一方客户启用密码凭据。但是如果没有客户机密,我如何确认它?任何其他应用程序都可以使用我的client_id并像第一方应用程序一样工作吗? - ssbb
4
公共客户端不知道如何保密刷新令牌,因此不应向它们发放;公共客户端唯一的安全性措施是强制预先注册的重定向URI,令牌将通过该URI交付。 - Hans Z.
非常感谢您的帮助 :) 那么,有一些最佳方法可以在公共设备上为第一方应用程序使用用户名/密码进行身份验证吗?就像所有流行的客户端一样 - Twitter,Google等。 - ssbb
如果您开发的应用程序将被多个第三方集成,并且您无法控制他们如何处理其应用程序中的安全性,那么默认情况下我是否应该将所有集成视为公共客户端? - CShark

7
@HansZ的回答是一个很好的起点,因为它阐明了公共和私有客户端应用程序之间的区别:保持客户端秘密的能力是一个秘密。但它并没有回答问题:哪些用例需要使用OAuth2档案?为了回答这个关键问题,我们需要深入探讨一下这个问题。
对于机密应用程序,客户端秘密是通过离线方式(OOB)提供的,通常是通过配置(例如在属性文件中)完成的。对于基于浏览器和移动设备的应用程序,实际上没有任何配置的机会,因此它们被认为是公共应用程序。
到目前为止,一切都还好。但我不同意这使得这些应用程序无法接受或存储刷新令牌。事实上,SPA和移动应用程序使用的重定向URI通常是"localhost",因此与直接从令牌服务器接收令牌响应资源所有者密码凭据授权(ROPC)100%相同。
许多作家指出,有时正确地指出OAuth2实际上并不执行身份验证。事实上,正如OAuth2 RFC 6749所述,ROPC和Client Credentials(CC)授权均需要执行身份验证。请参见4.3节和4.4节。
然而,对于授权码和Implicit授权,该陈述是正确的。但是对于这些领域,身份验证的实际工作方式是什么?
通常,用户将其用户名和密码输入到浏览器表单中,然后将其提交给身份验证服务器,并为其域设置cookie。很抱歉,即使在2019年,cookie也是身份验证技术的状态艺术。为什么?因为cookie是浏览器应用程序维护状态的方式。它们没有任何问题,浏览器cookie存储相对安全(受域保护,JS应用程序无法获取"http only" cookie,安全需要TLS/SSL)。Cookie允许只在第一次授权请求时呈现登录表单。之后,当前身份将被重复使用(直到会话过期)。
那么上述内容与ROPC有什么不同?没有什么区别。区别在于登录表单来源。在SPA中,应用已知来自TLS/SSL经过身份验证的服务器。因此,这几乎等同于直接由服务器呈现表单。无论哪种方式,您都可以通过TLS/SSL信任站点。对于移动应用程序,表单已知来自应用开发人员通过应用签名(从Google Play、Apple Store等应用程序中签名)。因此,这里存在类似于TLS/SSL的信任机制(不更好,也不更差,取决于存储、CA、受信任的根分发等)。
在这两种场景下,会返回一个令牌以避免应用程序在每个请求中都需要重新发送密码(这就是为什么HTTP基本身份验证不好的原因)。
在这两种情况下,认证服务器必须经过硬化,以抵御任何面向互联网的登录服务器所面临的攻击。授权服务器不会有这个问题,因为它们委托了认证。然而,OAuth2“密码”和“客户端凭据”配置文件都充当事实上的认证服务器,因此真的需要强大的安全性。
为什么你更喜欢ROPC而不是HTML表单?非交互式情况,例如CLI,是常见的用例。大多数CLI可以视为保密的,因此应该具有client_id和client_secret。请注意,如果在共享的OS实例上运行,则应编写CLI以从文件或至少标准输入中提取客户端密码和密码,以避免机密和密码在进程列表中显示!
本机应用程序和SPA也是另一个不错的用例,因为这些应用程序需要将令牌传递给REST服务。但是,如果这些应用程序还需要使用cookie进行身份验证,则可能要使用Authorization Code或Implicit流,并将委派认证给常规Web登录服务器。
同样,如果用户没有在与资源服务器相同的域中进行身份验证,则确实需要使用Authorization Code或Implicit授权类型。用户必须如何进行身份验证由授权服务器决定。
如果正在使用双重因素身份验证,则会变得棘手。我自己还没有跨越这个特定的桥梁。但是我见过像Attlassian这样的案例,可以使用API密钥允许访问通常需要除密码外的第二个因素的帐户。
请注意,即使您在服务器上托管HTML登录页面,您也需要注意它不会被浏览器中的IFRAME或本机应用程序中的某些Webview组件包装(可能能够设置钩子以查看您键入的用户名和密码,这就是密码管理器的工作原理)。但这是落在“登录服务器硬化”下的另一个话题,但答案都涉及客户端尊重Web安全惯例和对应用程序的一定信任水平。
最后两点:
1.如果通过任何流程类型安全地传递刷新令牌到应用程序,则可以将其安全地存储在浏览器/本机本地存储中。浏览器和移动设备相当好地保护此存储。当然,它比仅在内存中存储刷新令牌不安全。因此,也许不适用于银行应用程序......但许多应用程序具有非常长的生命周期(数周),并且就是这样完成的。
2.不要在公共应用程序中使用客户端密钥。它只会给你一种虚假的安全感。只有当存在安全的OOB机制来传递密钥并且它被安全地存储(例如锁定的OS权限)时,才适用于客户端密钥。

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