我正在尝试为应用程序选择正确的身份验证流:
- Fontend是一款只能通过HTTPS访问的渐进式Web应用程序。它是在有角度的单页应用程序中完成的
- 外部授权服务器
- 可通过REST调用访问后端
目前我正在使用授权代码授予流。
我试过什么:
- 我已经查看了官方网站。有一个可能的流列表(授权代码、隐式、密码、客户端凭据、设备代码…),但没有明确的指示如何在它们之间进行选择
- 然后我在Auth0.com上发现了这篇优秀的文章。不幸的是,PWA+服务器端的beckend没有出现在他们的方案中
你能告诉我什么OAuth2流适合我的上下文吗?为什么
假设(我理解问题的方式):
- 您拥有并开发前端(Angular应用程序)和后端(服务器端REST API)
- 您希望将身份验证外包给第三方身份提供商
- 您希望Angular应用程序(客户端)持有令牌,并能够在后端(资源服务器)上进行身份验证,在第三方(授权服务器/身份提供商(IdP))上建立您的用户(资源所有者)的身份
首先,一个侧轨。对于这个用例,OpenIdConnect(OIDC)会更适合,因为它支持identity元素。OAuth2的要点是授权您的应用程序在第三方上执行操作。你想要的是在第三方的帮助下建立用户的身份,这就是OpenId Connect所做的。
好的,那么哪个流(OIDC仍然基于OAuth2)。
第一个问题是是否信任客户端在资源服务器上执行任何操作,以及它是否可以安全地存储机密。事实显然并非如此,客户端应用程序不受信任,也不能保守秘密。在客户端凭据流中,客户端使用机密在IdP上进行身份验证,以接收资源服务器的令牌。这意味着你的Angular应用程序存储了一个密码,它用来为你的后端获取令牌,显然不是你想要的。
当客户端被信任处理用户凭据时,将使用资源所有者密码凭据流。在您的用例中,这是不好的,因为实际上这意味着您的Angular应用程序将获得用户密码,将其转发到IdP以换取令牌。您的客户端不应该访问用户密码,因为它不受信任。
现在是更有趣的部分。
问题是您的客户端是否有服务器端来安全地保存机密。如果是这样,授权代码授予是很好的,因为它允许您的用户在IdP上进行身份验证,使用授权代码重定向回来,然后服务器端可以将其交换为在资源服务器上使用的访问令牌。然而,在这种情况下,您的客户端没有服务器端,据我所知,API是资源服务器。所以这对你不好,因为它需要一个客户端机密,而你不能将其存储在你的Angular应用程序中。
这几乎给你留下了隐式流,你不需要客户端机密,但另一方面,很难做刷新令牌之类的事情。在您链接到的流程图中,最后一个问题是您的客户是否是SPA,在您的情况下是,因此您应该默认选择隐式流程。
这可能是对你来说最安全的模型,因为即使你的客户端受到威胁,你的用户凭据仍然是安全的(Angular应用程序永远无法访问)。
然而,您可以对整个事情进行不同的建模,这大大简化了它。
据我所知,您同时拥有客户端和资源服务器,而资源所有者正在使用客户端,您只想在第三方服务中管理用户的同时卸载身份验证。
这样看,您的客户端可以访问用户凭据,而使用它的用户是资源所有者。因此,您可以使用资源所有者密码流,用户将其凭据直接输入Angular应用程序,该应用程序将进入IdP,获得令牌,Angular只需使用该令牌访问API(资源服务器)上的内容。
与隐式流相比,风险在于,如果Angular应用程序被泄露,用户凭据将被泄露给攻击者。你是否愿意接受这种风险完全取决于你自己。请注意,如果IdP是一项知名服务(例如社交网站),这显然是行不通的,因为作为您的用户,我不想将我的社交网站密码提供给您的应用程序。但是,只要您管理用户,信任客户端是可以接受的。
虽然上一个anwser在2018年被完全接受,但现在应该考虑到它的安全风险。
IETF关于隐式流的来源。
现在用于PWA以及通常任何不能依赖client_secret的基于浏览器的公共客户端的正确流是授权代码流+PKCE