【发布时间】:2018-12-16 02:04:27
【问题描述】:
在过去的 10 多天里,我阅读了所有关于理解 OAuth2 和 OpenID Connect 的内容,但发现很多人不同意实施,这让我很困惑。
据我了解,我找到的所有文章和示例都假设您想访问例如。谷歌日历,个人资料信息或电子邮件,如果你例如。用谷歌登录,但我不需要访问除我自己的 API 之外的其他东西——我只想使用谷歌、Facebook 等登录,并获得一个我可以在我自己的数据库中链接到我的用户的 ID——仅此而已.
我将尝试说明我的用例并将其用作示例。
图表上的一个注释:身份验证服务可能会内置到 API 网关中——我对这个例子并不重要,因为这不是关于“在哪里做”,而是“如何做”最好的方法”,对于像我这样的架构,它用于我自己的 API/微服务,而不是访问 Google、Facebook 等外部 API
如果您能理解我想用上图说明的内容,请告诉我是否误解了这一点。
您在此处看到的此架构的最基本要求是:
- 用户可以使用谷歌、Facebook等登录。
- 所有微服务都将使用相同的登录名
- OpenId 用户将在数据库中拥有一个关联的帐户
- 用户访问权限在我自己的数据库中定义,基于组、角色和权限
我不打算在用户通过身份验证并登录后使用外部 API。不需要访问用户日历、电子邮件等。所以我真的只需要身份验证部分而不需要其他任何东西(成功登录的证明)。所有用户访问都在我自己的数据库中定义。
所以我想到了几个基本问题。
- 首先,OpenID Connect 是否是仅用于身份验证的正确工具(我不会使用授权,因为除了从身份验证)?
- 人们通常不同意是使用 ID 还是访问令牌来访问您自己的 API。据我了解,ID 令牌仅用于客户端(用户代理),而访问令牌用于例如。访问谷歌日历、电子邮件等...... OpenID 提供者的外部 API......但由于我只会访问我自己的 API,我是否需要访问令牌或 ID 令牌 - 保护的正确方法是什么您自己的 API?
如果 ID 令牌真的只是用于客户端,那么它可以显示例如。当前登录的用户,没有去数据库,我有 0 使用它,因为我可能会从数据库中查询用户并将其存储在我的反应前端应用程序的 redux 中。
困境:将用户详细信息、组、角色和权限存储在 JWT 中还是不用于 API 授权?
- 通过仅将用户标识符存储在令牌中,这意味着我始终允许具有有效令牌的经过身份验证的用户在授权之前调用端点,然后首先根据 db 查询结果和我自己的数据库中的权限确定访问权限.
- 通过在 JWT 中存储更多关于用户的数据,这意味着在某些情况下,我可以在访问 API 之前进行授权/访问(组、角色、权限)检查 - 只有用户信息才有可能,组,角色和权限存储在登录时发出的 JWT 中。在某些情况下,由于例如,这是不可能的。 CMS 内容访问权限在每个节点级别。但这仍然意味着更好的性能。
如图所示,我通过网关发送所有 API 请求,网关(本身或使用身份验证服务)将不透明的访问令牌转换为带有标识符的 JWT,因此我可以识别用户在图形数据库中 - 然后验证用户是否具有所需的组、角色和权限 - 不是来自外部 API,而是来自我自己的数据库,如图所示。
这似乎对每个请求都进行了大量工作,即使服务可以共享 JWT,以防多个服务需要相互交叉调用。
始终查找用户及其在数据库中的权限的好处自然是,当用户访问级别发生更改时,他会立即被拒绝/授予访问权限,并且始终保持同步。如果我将用户详细信息、组、角色和权限存储在 JWT 中并将其保存在客户端本地存储中,我想这可能会造成安全问题,并且很难更新用户信息、组、角色和权限在那个 JWT 里面?
在 JWT 中存储用户访问级别和信息的一大优势当然是,在许多情况下,我可以阻止用户调用某些 API,而不必在查找数据库后确定访问权限。
因此,整个令牌转换意味着以性能为代价提高安全性,但通常推荐并且值得吗?或者在 JWT 中存储用户信息和组、角色、权限是否足够安全?
如果是,我是否将我自己的数据库中的所有信息存储在 ID 令牌、访问令牌或第三个令牌中 - 将什么令牌发送到 API 并确定是否应授予用户访问给定资源的权限他在数据库中的权限?如果我不需要与 ID 提供者 API 交互,我真的需要访问令牌吗?或者我是否将我的所有组、角色、权限存储并附加在由 OpenID connect 发布的 ID 令牌(对我来说似乎并不干净)中,并调用 API 并使用它授权我自己的 API 端点,即使有人说你永远不应该使用 ID 令牌来访问 API?还是创建一个新的 JWT 来存储从我的数据库中获取的所有信息,用于决定用户是否可以访问给定的资源/API 端点?
请不要只链接到一般规格或一般信息,因为我已经阅读了所有内容 - 我只是不明白如何将所有这些信息应用于我的实际用例(上图)。尽量做到具体一点。
再次尝试简单的流程:
【问题讨论】:
-
您是在实现 API 管理器还是会使用现有的管理器?
-
我不确定您所说的“API 管理器”是什么意思,但用高级语言制作一个非常基本的 API 网关/反向代理(使用一些库)应该相当容易例如 Go (golang),这是我将使用的。
-
如何/何时在数据库中创建用户?您从哪里获得用户详细信息?
-
我猜是最正常的方式。我计划使用相同的登录框执行此操作 - 唯一的区别是如果找不到“链接”用户(通过电子邮件或某些标识符?)它将被创建,其中包含来自 Google/Facebook 登录的电子邮件和第一个/最后一个来自身份验证的名称。因此,实际上在第一次使用 Google/Facebook 等登录时,获取最基本的用户详细信息将很有用。但再也不会,在创建用户之后。
标签: oauth-2.0 jwt microservices openid-connect