【问题标题】:Authorization and Authentication in microservices - the good way微服务中的授权和身份验证——好方法
【发布时间】:2022-01-14 13:22:52
【问题描述】:

我正在考虑微服务架构,但我在授权和身份验证方面遇到了困难。我找到了很多关于 oauth2openid connect 的资源,声称他们解决了问题,但对我来说还不够清楚。

假设我们有以下架构:

在我的系统中,我只想为role 定义的特定group 用户添加一项功能。我还想知道用户的name,他们的emailid

经过研究,我发现以下解决方案是一个好的开始:

  1. SPA 应用程序显示login form
  2. 用户填写表格并向authN&authZ server发送POST请求。
  3. 服务器回复access token(作为JWT),其中包含用户的nameemailidrole。响应还包含 refresh token
  4. SPA 应用程序存储令牌并将其附加到它发出的每个请求中。
  5. Microservice 1Microservice 2 检查令牌是否有效。如果是,他们检查角色是否正确。如果是这样,他们会获取用户信息并处理请求。

我离好的解决方案还有多远?登录流程看起来像 Implicit flow with form post 描述的 here 但有隐式同意,我不确定它是否正常。

展望未来,我发现在JWT(例如nameemail)中传递用户数据并不是一个好的解决方案,因为它会暴露敏感数据。我发现资源说建议只在令牌中公开对用户的引用(例如ID),并在向微服务发送请求时将此类令牌替换为reverser-proxy/api gateway 中的经典access_token .考虑到这样的解决方案,我认为以下场景是一个好的开始:

  1. SPA 应用程序显示login form
  2. 用户填写表格并向authN&authZ server发送POST请求。
  3. 服务器回复access tokenrefresh token。 API 网关(中间)将 access token 替换为 ID token,并将访问令牌中的声明存储在其缓存中。
  4. SPA 应用程序存储令牌并将其附加到它发出的每个请求中。
  5. 处理请求时,API Gateway 接受 ID Token 并根据用户 ID 生成新的 access token。访问令牌被发送到微服务 1 或微服务 2,并像以前一样对其进行验证。

您如何找到这样的解决方案?这是一种安全的方法吗?我应该如何改进建议的流程?

提前致谢!

【问题讨论】:

  • 您应该考虑将您的集群设为私有,并利用 api 网关作为唯一公开的 api 来处理您的所有身份验证。您的身份验证应该是第一道防线。在您的微服务之前。
  • 你考虑过使用 BFF 模式吗? blog.bitsrc.io/…
  • @exceptionsAreBad 感谢您的回答。当然,微服务应该在私有集群中,API 网关是唯一公开的 API。我希望我在我的问题中提出的图表能够呈现它。 API Gateway 也负责处理身份验证。我的问题更多是关于如何处理身份验证。
  • @ToreNestenius 感谢您的回答。是的,我正在考虑使用 BFF 模式,但在我的问题中,外部 API 组件是 API Gateway 还是 BFF 并不重要。在我的示例中,只有一个客户端,所以实际上 API 网关是 BFF。

标签: oauth-2.0 architecture microservices openid-connect


【解决方案1】:

你在正确的轨道上:

零信任

这是一种新兴趋势,每个微服务都使用库验证 JWT - 请参阅 this article。 JWT 验证速度很快,并且可以扩展。

客户的机密令牌

互联网客户端应该无法读取 API 使用的声明。网关概念中的交换令牌是正确的,但通常的方法是在这里发布不透明的访问令牌,而不是使用 ID 令牌。在 Curity,我们称之为Phantom Token Approach

浏览器中的安全 Cookie

需要注意的一个方面是在浏览器中使用令牌。这些天SameSite=strict HTTP Only cookie 是首选。不过,这需要更复杂的流程。有关安全性的一些建议,请参阅SPA Best Practices

SPA 应该顺便使用代码流 - 旨在避免隐式流,因为它可能会泄漏浏览器历史记录或 Web 服务器日志中的令牌。

摘要

以上所有都是针对的通用安全设计模式,无论您的授权服务器如何,当然,一次一步达到目标是很常见的。

【讨论】:

  • 感谢您的回答!幻影令牌听起来真的很有用:)
【解决方案2】:

不要使用您自己的登录表单。正如 Garry Archer 所写,将身份验证代码流与 PKCE 结合使用,即 recomended flow 用于在浏览器中运行的应用程序。

如果您不想获取 ID 令牌,请不要在初始身份验证请求中要求 openid 范围。颁发的访问令牌的类型(JWT 或不透明)通常可以在您的 OAuth2 服务器上配置。所以我认为没有必要在你的网关上发行新的令牌。拥有更多的令牌发行者会打开更多攻击您的系统的方式。

您的后端模块可以使用userinfo endpoint,这将为他们提供有关用户的信息并验证令牌。这样,如果令牌无效(例如用户注销),请求处理将不会继续。如果您只验证 JWT 签名,您将不会知道令牌是否失效。

如果您计划在后端模块之间发出请求作为用户请求处理的一部分,只要您的模块处于安全环境(例如一个 Kubernates)中,您就可以使用从您的 SPA 收到的原始访问令牌。

【讨论】:

  • 感谢您的回答。我正在考虑自己的登录表单。我考虑例如作为微服务系统构建的电子商务应用程序。它包含自己的身份验证服务器。我不想使用 Facebook 等第三部分提供商。在这种情况下,实现自己的登录表单对我来说听起来很合理,只需向身份验证服务器(通过网关)发送令牌请求,然后简单地获取访问权限并刷新令牌作为响应。即使客户是SPA。这样的解决方案在他关于微服务的书中提出了 Chris Richardson。这对你有意义还是我错过了什么?
  • 使用您的身份验证服务器登录表单通常没有什么优势,这可能与您相关,也可能不相关。用户通常比您的应用程序更信任身份验证服务器(它可能通过了一些安全审核)。如果您的应用程序处理用户的凭据,您有责任确保他们不会受到损害。另一件事是使用单点登录的可能性。我想到的最后一件事是可以轻松使用更复杂的身份验证机制,例如开箱即用的第二因素身份验证。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-11
  • 1970-01-01
  • 2017-12-17
  • 2018-01-18
  • 2020-10-21
相关资源
最近更新 更多