您问题的答案可以是代码级别,协议级别或体系结构级别。我将在这里尝试总结大多数协议级别的问题,因为这在利弊分析中通常至关重要。请记住,OAuth2远不止资源所有者密码凭证(根据规范,该凭证是出于“旧版或迁移原因”而存在)的,被认为“比其他授予类型的风险更高”,并且该规范明确指出客户端和授权服务器“应尽量减少使用此授权类型,并尽可能使用其他授权类型”。
与基本身份验证相比,使用ROPC仍有许多优点,但是在深入探讨之前,让我们了解OAuth2和基本身份验证之间的基本协议区别。在我解释这些内容时,请多多包涵,稍后再来ROPC。
用户认证流程
OAuth2规范中定义了四个角色。通过示例,它们是:
- 资源所有者:有权访问某些资源的用户,例如,在您的情况下,不同的用户可能对REST API具有不同的访问级别;
- 客户端:通常是用户正在使用的应用程序,需要访问资源以向用户提供服务;
- 资源服务器:您所用的REST API;和
- 授权服务器:向其提供用户凭据并对其进行身份验证的服务器。
客户端应用程序运行时,将根据用户被授予对资源的访问权限。如果用户具有管理员特权,则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),客户端(例如,他们的移动应用程序)和用户。我希望这种解释能有所帮助。