OAuth2授权代码流-在前端与后端上交换授权代码



我正在用Angular Frontend和Java/Spring Backend开发一个应用程序。为了登录我们的后端,我们使用Oauth2授权代码流与PKCEOpen ID Connect

当用户导航到受保护的路由时,他被重定向到他的IDP,并且必须登录。之后,他被返回到一个以authorization_code作为URL参数的redirect_uri。到目前为止一切都很清楚。

现在我不确定用这个代码交换access_token的最佳方式是什么?到目前为止,我已经在客户端(用JavaScript)上完成了这项工作,并将接收到的JWT用于进一步的后端调用(在后端,我只是验证签名),这似乎确实有效。但在其他项目中,我看到同事们实际上使用了后端,有点像代理。因此,他们将authorization_code发送到Java后端,后端进行交换。

现在我读了很多书,但似乎无法理解其中的全部含义。在我看来,让客户/前端这样做更安全。但另一方面,后端实际上是受信任的,所以在这种情况下,我们实际上可以使用client_secret。

现在的问题是:这两种情况都被认为是安全的吗?还是一个被认为更安全?如果是,为什么?

提前感谢

*编辑:只是澄清一下-我们真的不需要访问另一个资源服务器,用例是我们只想通过到我们自己的后端的安全身份验证-一旦通过身份验证,我们无论如何都会切换到会话cookie,所以我们根本不在任何地方存储access_token

将令牌保留在后端总是一种更安全的方法,因为它减少了攻击面,并使客户端中的代码更加简单。

一个好的起点是看看这个BCP

  • 用于基于浏览器的应用程序的OAuth 2.0(第6.2节)

另一个参考是:

  • 备忘单:基于浏览器的应用程序的OAuth(例如JavaScript SPA)

为了简化JavaScript,我会在后端进行所有客户端身份验证,当后端获得令牌时,然后创建与客户端的会话。通过这种方式,JavaScript客户端不需要触摸任何令牌。您的内部资源/API将通过负责会话的服务进行访问。干净简单!:-)

是的!我认为典型的错误是让JavaScript触摸您的代币。知道令牌只在后台处理,你晚上会睡得更好。此外,减少了安全复杂性和您必须掌握和理解的内容我们必须与复杂性作斗争

实际授权码只能使用一次,因此无论是从前端还是后端发送都无关紧要。

这里有两种常见的模型:

选项1:WEB后端/代理模式

如果您想将令牌排除在浏览器之外,并使用仅HTTP cookie作为后端凭据,则使用此选项:

  • Web后端发布同一域HTTP纯cookie,并将令牌存储在数据库或cookie本身中
  • Web UI通过首先使用cookie调用Web后端来进行所有API调用
  • Web后端然后查找令牌并将其转发到API
  • 您需要应对CSRF和XSS等网络威胁

挑战包括:

  • 比您想要的更复杂
  • 一些体系结构限制

选项2:SPA模式

这是您正在使用的跨域模型,在技术上更简单::

  • Web UI通过发送访问令牌进行API调用
  • 您需要应对XSS等威胁,并特别关注确保在浏览器中使用代币的安全性不亚于使用cookie
  • 您需要在浏览器中以安全的方式存储令牌,例如在内存中

挑战包括:

  • 如果您的安全性存在漏洞,则更容易利用漏洞,因为用户可以更容易地查看自己的令牌
  • 在这个模型中,令牌续订和跨标签导航方面比较棘手

因素

以下是做出选择时的主要因素:

  • 安全威胁模型-令牌与cookie及其他因素
  • Web UI更广泛的体系结构目标
  • 利益相关者的感知通常是最大的考虑因素

无论你做什么决定,我都建议从需求开始,而不是从特定的技术堆栈开始。

矿山资源

我更喜欢选项2,因为我认为架构选项要好得多,但它需要小心。以下链接有望帮助您了解我是如何推理出我的首选解决方案的:

  • Web架构目标
  • 威胁模型-Cookies v代币
  • 最终状态和云部署

但并不是每个人都同意我的观点。有时在软件中有多种解决方案。重要的是要涵盖安全威胁。您可以使用任一解决方案来实现这一点。

当您从客户端调用令牌时,它不是授权流,而是隐式流,当您没有后端时可以使用它,当您有后端时,您应该始终使用您提到的授权代码流。您可以在这里了解更多关于openid流的信息。

授权代码流被认为更安全,因为它使用带有idp的反向信道通信(服务器到服务器)来接收令牌,而隐式流从浏览器发送请求。

使用PKCE发送客户端调用是一项新技术,它被认为是安全的,但授权代码流无疑是后端的更好选择。

最新更新