适用于公共REST API的OAuth2 ROPC与基本身份验证?


21

我在这里感兴趣的特定用例是针对可公开使用的服务器端点(例如,公共REST API)对REST客户端进行身份验证。

这里最简单的解决方案是Basic Auth。但是我经常听到OAuth2在几乎所有情况下都被视为一种出色的身份验证解决方案。

事实是,对于REST客户端针对REST服务器进行身份验证的唯一可行的OAuth2授予​​类型是资源所有者密码凭证(ROPC),因为代码授予和隐式授予要求用户界面/网页(由Auth服务器托管)用户登录并手动授权客户端应用。

ROPC的工作方式是,通过发送资源所有者的用户名/密码和客户端ID作为查询字符串参数?这比基本身份验证(IMHO)更为不安全,基本身份验证至少使用base-64对凭据进行编码,然后将其发送到可以由TLS加密的标头中!

所以我问:在公共REST API的上下文中,OAuth2 ROPC是否真的比Basic Auth更好?有什么比OAuth2 ROPC更安全的?


更新资料

我刚刚读了这篇出色的文章,解释了Amazon针对AWS的非基于OAuth2的REST安全性。从本质上讲,这是一个基于私钥的解决方案,其中,每个REST请求的哈希都将生成,并作为sidecar与常规(未加密)请求一起发送。只有客户端和服务器知道私钥,因此,当服务器接收到该请求(再次包含普通请求+散列请求)时,服务器将查找客户端的私钥,将相同的哈希应用于普通请求,并然后比较两个哈希。

这听起来比OAuth2的ROPC更加复杂,复杂和安全!除非我在这里缺少一些重要的东西,否则OAuth2 ROPC只会发送client_idusername并且password作为查询字符串参数...完全完全不安全!这种基于HMAC /哈希的解决方案似乎更加令人印象深刻和安全。

问题是,即使是该文章的作者也继续说:

您[也会]慢慢意识到并接受在某个时候您将必须实现OAuth ...

巴巴巴哇?!?!如果OAuth2的安全性不如此聪明的基于HMAC /哈希的解决方案,那么为什么本文的作者感到在某些时候需要使用OAuth。我很混乱。


您在说什么样的客户?我假设大多数客户端都将具有UI。在这种情况下,您可以在Web视图(台式机,移动设备)中加载OAuth登录页面,或直接通过Web视图重定向到该页面。我不明白为什么您需要避免UI。
decyclone

@decyclone请阅读问题的第一句话!我正在考虑针对REST服务进行身份验证的REST(无头HTTP)客户端。
smeeb

我要问的问题是该客户端是否具有任何UI?即使没有,我也看到没有UI的应用程序至少会弹出一个对话框以进行身份​​验证。
decyclone 2015年

@decyclone没有纯REST客户端,也没有UI,尽管UI通常使用纯REST客户端来连接到REST服务。一个用例是一个命令行工具,该工具使用REST客户端将用户命令(在外壳上输入)发送到REST服务。从外壳弹出UI只是这里不可接受的解决方案。
smeeb

1
但是,我应该注意,命令行/ shell之外还有许多其他用例。另一个用例是没有UI的Java / Ruby / Python纯REST / HTTP客户端,并且可能在没有UI的后端服务器上运行。后端服务器需要通过REST与另一台后端服务器进行通信。在这里,当后端服务器#1需要与后端服务器#2对话时弹出一个UI不仅笨拙而且笨拙,真正的问题是没有浏览器/ UI客户端可以显示登录页面,而且没有人工操作在那里登录!!!
smeeb

Answers:


24

您问题的答案可以是代码级别,协议级别或体系结构级别。我将在这里尝试总结大多数协议级别的问题,因为这在利弊分析中通常至关重要。请记住,OAuth2远不止资源所有者密码凭证(根据规范,该凭证是出于“旧版或迁移原因”而存在)的,被认为“比其他授予类型的风险更高”,并且该规范明确指出客户端和授权服务器“应尽量减少使用此授权类型,并尽可能使用其他授权类型”。

与基本身份验证相比,使用ROPC仍有许多优点,但是在深入探讨之前,让我们了解OAuth2和基本身份验证之间的基本协议区别。在我解释这些内容时,请多多包涵,稍后再来ROPC。

用户认证流程

OAuth2规范中定义了四个角色。通过示例,它们是:

  1. 资源所有者:有权访问某些资源的用户,例如,在您的情况下,不同的用户可能对REST API具有不同的访问级别;
  2. 客户端:通常是用户正在使用的应用程序,需要访问资源以向用户提供服务;
  3. 资源服务器:您所用的REST API;和
  4. 授权服务器:向其提供用户凭据并对其进行身份验证的服务器。

客户端应用程序运行时,将根据用户被授予对资源的访问权限。如果用户具有管理员特权,则REST API中该用户可用的资源和操作可能远远超过没有管理员特权的用户。

OAuth2还允许将单个授权服务器与多个客户端和多个资源一起使用。例如,资源服务器可以接受用户使用Facebook的身份验证(在这种情况下可以充当授权服务器)。因此,当用户运行应用程序(即客户端)时,它将用户发送到Facebook。用户在Facebook中键入其凭据,客户端将获得一个“令牌”,可以将其呈现给资源服务器。资源服务器在验证Facebook实际上已颁发令牌并允许用户访问该资源之后,查看令牌并接受令牌。在这种情况下,客户端永远不会看到用户的凭据(即他们的Facebook凭据)。

但是,假设您是在管理用户的身份(并且具有授权服务器)而不是Facebook,后者已经向您的客户端授予了令牌。现在,假设您还有一个合作伙伴,并且想要允许他们的应用程序(即客户端)访问您的REST API。使用基本身份验证(甚至ROPC),用户将向该客户端提供凭据,然后将其发送到授权服务器。然后,授权服务器将提供一个令牌,客户端可以使用该令牌来访问资源。不幸的是,这意味着该客户端现在也可以看到用户的凭据。但是,您甚至不希望合作伙伴的应用程序(可能在组织外部)知道用户的密码。现在这是一个安全问题。为了实现这个目标,

因此,使用OAuth2,理想情况下,在这种情况下,不使用ROPC,而使用其他代码,例如授权代码流。这样可以防止任何应用程序知道仅提供给授权服务器的用户凭据。因此,不会泄露用户的凭据。基本身份验证也存在相同的问题,但是在下一节中,我将说明ROPC仍然更好,因为客户端仍不需要将用户的凭据存储在ROPC中以供客户端进行持久访问。

请注意,当用户转到授权服务器时,授权服务器还可以要求用户确认是否要允许客户端代表他们访问资源。这就是为什么将其称为 授权服务器的原因,因为该过程涉及授权客户端访问资源的过程。如果用户未授权客户端,则它将无法访问资源。同样,如果用户本身无权访问资源,则授权服务器仍可以拒绝访问并且不发出令牌。

在基本身份验证中,甚至将授权服务器和资源服务器也组合为一个实体。因此,资源服务器要授权用户,因此从客户端询问凭证。客户端提供那些由资源服务器用来认证用户的凭据。这意味着多个资源服务器将本质上要求用户提供凭据。

代币发行

客户端从授权服务器获取令牌,保留它们并使用它们访问资源(下面有关令牌本身的更多详细信息)。客户端永远不会知道用户的密码(在ROPC之外的流程中)并且不需要存储它。在ROPC中,即使客户端确实知道用户的密码,他们仍然不需要存储密码,因为它们使用这些令牌来访问资源。相比之下,在基本身份验证中,如果客户端不想让用户在每个会话中提供凭据,则客户端必须存储用户的密码,以便下次可以提供该密码。这是使用基本身份验证的主要缺点,除非客户端只是一个Web应用程序,在这种情况下,Cookie可以解决其中的一些问题。对于本机应用程序,通常不是一种选择。

OAuth2的另一方面涉及令牌的发行方式和工作方式。当用户向授权服务器(甚至在ROPC中)提供凭据时,授权服务器可以提供两种类型的令牌中的一种或多种:1)访问令牌,以及2)刷新令牌。

访问令牌被发送到资源服务器,该资源令牌将在验证资源后授权访问资源,通常它们的生存期很短,例如1小时。客户端将刷新令牌发送到授权服务器,以在到期时获得另一个访问令牌,并且访问令牌通常具有很长的生存期(例如几天至几个月甚至几年)。

当客户端将访问令牌提供给资源服务器时,它将查看令牌,并在验证之后在令牌内部查找以确定是否允许访问。只要访问令牌有效,客户端就可以继续使用它。假设用户关闭应用程序并在第二天启动它,并且访问令牌已过期。现在,客户端将调用授权服务器,并在未过期的情况下显示刷新令牌。由于授权服务器已经发出了令牌,因此对其进行验证,并可以确定用户不需要再次提供凭据,从而将另一个访问令牌提供给客户端。客户端现在可以再次访问资源服务器。通常,这是Facebook和Twitter的客户端应用程序一次要求提供凭据,然后不需要用户再次提供凭据的方式。这些应用程序永远不需要知道用户凭据,但是每次用户启动应用程序时都可以访问资源。

现在,用户可以进入授权服务器(例如,在其Facebook用户配置文件中),更改密码而不会影响任何客户端应用程序。它们都将继续正常运行。如果用户丢失了已经拥有带有刷新令牌的应用程序的设备,则他们可以告诉授权服务器(例如Facebook)通过不遵守任何现有的方法来“注销”授权服务器(例如Facebook)将完成的那些应用程序刷新令牌并强制用户在尝试通过那些应用程序访问资源时再次提供凭据。

JWT只是OAuth2和OpenID Connect通常使用的令牌格式。签名和验证令牌的方法也通过适用于这些库的库进行了标准化,而不是每个资源服务器都实现了另一种解决方案。因此,优点在于已审查并继续受支持的代码的可重用性。

安全隐患

当以上任何一种情况出现在图片中时,基本身份验证将变得较弱。对于OAuth2来说,还有一个广泛的威胁模型可供开发人员使用,他们可以使用其中的建议来避免其实现中的常见漏洞。如果您经过威胁模型,您会发现其中也涵盖了许多与实现相关的漏洞(例如开放重定向器和CSRF)。在此响应中,我没有将这些认证与基本认证进行比较。

OAuth2的最后一个主要优点是该协议是标准化的,并且有多个授权服务器,客户端和资源服务器使用该协议。开发人员可以使用许多库,这些库得以维护,以便在实现中发现安全问题,并在允许互操作性的同时更新库。

结论

如果要编写新的应用程序IMO,则理想的情况是避免基本身份验证和ROPC,因为它们固有的问题。但是,每个应用程序都有不同的需求,时间表,开发人员的熟练程度等,因此,决定视情况而定。但是,即使您只需要基本身份验证,通过选择它,您也可以将自己锁定在一个可能难以扩展的体系结构中(例如,如果将来有多台服务器,则不一定要拥有用户向他们中的每个人提供凭据,而不是只提供给授权服务器一次,后者可以分发令牌等)。

请注意,由于您可以使用TLS或类似协议或所有权证明来对凭证进行安全保护,因此我没有就您如何通过网络发送凭证发表评论。正如有人已经建议的那样,base 64编码是0安全性,请不要被那迷住了。上面提到的差异通常是在体系结构级别上,因此我将重点放在这方面,因为一旦实现,体系结构就很难更改。

我正在使用的Azure Active Directory B2C Basic服务已发布,最近已发布以供公众预览,它允许第三方应用程序将AAD用作授权服务器,并与社交IDP(例如Facebook,Google等)互操作。它还允许用户创建自己的帐户,而不是使用社交IDP,以后可以将其用于身份验证目的。还有其他一些类似的服务(例如,我知道的另一个服务是auth0),开发人员可以使用它完全将其应用程序和资源的身份验证和用户管理外包出去。开发人员使用我上面提到的相同协议特征来解耦授权服务器(AAD),资源(例如,他们的REST API),客户端(例如,他们的移动应用程序)和用户。我希望这种解释能有所帮助。


非常感谢,但是我不认为这些优点(a) letting the user agent hold just the token instead of the password, (b) allowing a password change without disrupting existing client apps, (c) allowing users log out other sessions是令牌身份验证流程所特有的。基本身份验证和令牌身份验证均未在其规格中提及函数(b)和(c)。对于任何类型的身份验证,似乎都可以实现(b)和(c)。它将涉及跟踪密码(最好是其哈希值)。优点(a)似乎取决于密码的范围。
eel ghEEz

如果用户(资源所有者)在外部授权服务器上没有任何凭据,但在客户端应用程序中具有凭据,我们如何使用OAuth?也就是说,我们有资源所有者(用户),客户端(代表用户并且还包含用户凭据)和资源服务器。资源服务器如何认证和授权用户?
阿伦·阿瓦娜森

3

我相信您对URL中GET变量周围的加密有误解

可以在请求中查看GET变量的唯一人员是原始计算机和接收服务器(链接)。

仅基于HTTPS请求发送到的域的DNS查找不会被加密。端口,GET变量,资源ID等所有其他内容均已加密。

唯一需要注意的是,接收服务器可以注销完整的请求路径,但是您可以控制该路径,因此可以在认为合适的情况下保护该数据。


3

基本身份验证不是保护REST API的好方法。我解释了此答案的原因。

在构建REST API时,您将以OAuth2术语实现资源服务器。您API所需要做的就是验证与授权HTTP标头中的请求一起传递的令牌是有效的,并且来自受信任的颁发者。如果没有可用的库,请参阅此链接以获取有关如何实施验证的步骤。

您的客户端如何从授权服务器获取令牌取决于它是哪种客户端。请记住,在授权服务器上注册客户端时,需要指定要使用的客户端类型。

如果Web应用程序与您的服务器通信,则可以使用授权代码grant。如果它是不可信的客户端(例如移动应用程序或JavaScript应用程序),则应使用隐式Grant

对于无法与资源所有者交互的后端服务,您可以使用客户端凭据grant。对于命令行工具,您可以使用客户端凭据或资源所有者密码grant

这完全取决于您使用的客户端类型。

最后,验证JWT令牌发生在资源服务器上,而无需与授权服务器对话。与需要为每个客户端查找私有数据的解决方案相比,这导致了更好的可伸缩体系结构。


1

它是安全的还是不安全的。不多不少。使用base64不会使“基本​​身份验证”(或其他任何内容)更加安全。

如果使用的是像Https这样的加密管道,则发送未加密的任何内容都没有错。

OAuth 具有更多功能,请在需要时使用它。对于其他任何事情,例如银行业务,使用基本质询-响应都是很好且安全的。


0

我认为您需要首先了解术语。您正在比较- 授权数字签名

OAuth是授权的开放标准,在此过程中,亚马逊正在做的事情(根据问题所提供的文章和详细信息)正在创建有效的数字签名,该签名使收件人(在此为Amazon)有理由相信该消息是由已知的人创建的发件人,发件人不能拒绝已发送消息(身份验证和不可否认)

对于哪种授权机制,它或多或少取决于您的用例。

以下是可在StackOverflow上找到的内容

基本身份验证需要非常简单的哈希才能计算出所需的单个标头-毫无疑问,OAuth是更昂贵的身份验证。要意识到的重要一点是,两种身份验证机制的用途完全不同。基本身份验证用于向主应用程序验证客户端。OAuth用于授权第三方从主应用程序访问客户端数据。两者都有自己的位置,应根据实现的特定用例来选择一个。

这是另一篇比较两者的有趣文章

从简单的安全角度来看,基于SSL的基本身份验证实际上是相当负责的。当我们争用用户名和密码时,基本身份验证是一种流行的解决方案,因为它很容易实现。凭证的传输通过SSL加密,HTTP客户端和系统中普遍使用“授权”标头。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.