我认为我们在 Gitter 上进行了非常简短的交谈,我已经说过这取决于您的用例。我将简要介绍典型用例,以及您在哪些地方需要哪种附加实现。
机器对机器通信
如果您需要两个系统从后端相互通信,并且这些系统相互信任,您可以使用 OAuth2“客户端凭据流”。在这种情况下,不涉及“最终用户”身份,只涉及明确相互信任的两个系统。
对于这种情况,Kong 是您所需要的一切 - 您只需向 Kong 的 API 令牌端点(<address of kong>:8443/your_api/oauth2/token 用于基于 URI 的路由,或 fqdn.of.kong:8443/oauth2/token 如果您使用基于主机的路由)使用您的客户端获取访问令牌ID 和 Secret,你会得到一个。
例子:
curl --insecure -d 'grant_type=client_credentials&client_id=<...>&client_secret=<..>' https://<address of kong>:8443/your_api/oauth2_token
您的后端服务将注入一些额外的标头,例如映射到您在 Kong 中创建的消费者的 X-Consumer-Id 和 X-Custom-ConsumerId。
具有最终用户上下文的机密 Web 应用程序
如果您需要从机密 (=classic) Web 应用程序中使用 API,并且每次调用都需要最终用户上下文,您可能需要使用 OAuth2“授权代码授予”。在这种情况下,您还需要一个您需要自己实现的授权服务器。
授权服务器的任务是建立最终用户身份(请注意:这未在 OAuth2 中指定如何完成,这取决于您;您可以联合其他一些IdP,您可以询问用户名和密码,...),然后决定用户在访问 API 时获得哪些权限 (="scopes")。这完全取决于您,以及您的部分业务逻辑如何决定。
流程是这样的:
- 您(重新)将用户定向到授权服务器的网页
- AS 对用户进行身份验证(通过任何方式)并决定范围(通过任何其他方式)
-
AS 在两个不同层面上与 Kong 对话
- 通过 Kong Admin API,检索所需 API 的
provision_key
- 通过
[/your_api]/oauth2/authorize端点,它用于在经过身份验证的用户及其范围(scope和authenticated_userid)的上下文中获取包含授权代码的重定向URI;要调用此端点,您将需要response_type=code、client_id、client_secret、provision_key、authenticated_userid(任何合适的)和可选的scope(还需要在 API 上定义范围,如果你想用这个)
如果成功,AS 使用 Kong 返回的重定向 URI 重定向回 Web 应用程序
- Web 应用程序调用 Kong 的
[/your_api]/oauth2/token 端点及其 client_id、client_secret 和 code,使用 grant_type=code
现在您将拥有一个访问令牌(和一个刷新令牌),它允许您的 Web 应用程序代表经过身份验证的用户访问 API。
授权服务器必须由您实现;这不是很复杂,但您仍然需要确保您知道如何验证用户身份,和/或如何将其委托给其他 IdP。
具有最终用户上下文的公共客户端(单页应用程序)
如果您需要从单页应用程序(例如从 Angular 应用程序或类似应用程序)访问 API,您应该查看 OAuth2“隐式流程”,它比授权代码授予更简单,但是还有其他缺点,例如无法使用刷新令牌。
此流程的工作方式如下:
- 就像授权码授予一样,您将用户重定向到授权服务器
- AS 建立身份并决定范围(再次,这取决于您)
- AS 调用授权端点,就像授权码授权一样,但这次是
response_type=token
- Kong 如果成功,将返回一个重定向 URI,该 URI已经包含一个令牌
- AS 使用来自 Kong 的重定向 URI 重定向回 SPA,该重定向 URI 在 URI 的“片段”中具有访问令牌(例如
https://your.app.com/#access_token=<...>&token_type=bearer&...)
您的 SPA 现在将能够使用访问令牌来访问 API,就像授权代码授予一样,代表经过身份验证的用户。
这种方法的缺点是您不能(那个)轻松地刷新令牌,而且它的安全性比授权码授予的稍差。但是在处理 SPA 时,没有很多其他安全的方式来委派对它的访问。
移动应用程序
我想在这里讨论的最后一个场景是移动应用程序,例如 Android 或 iOS 应用程序。对于这些,可以使用最后一个 OAuth2 流程,即“资源所有者密码授予”。简而言之,通过此授权,您可以根据访问令牌和刷新令牌交换实际的用户凭据(用户名和密码),这样您就不必在移动设备上临时存储用户名和密码。
这个流程还需要一个授权服务器才能与 Kong 一起使用,尽管这次不太复杂,尽管您必须实现一个额外的 token 端点(除了 Kong 所拥有的端点),即在 Kong 文档中没有理想地描述。
应该是这样的:
- 移动应用程序使用其
client_id(不是秘密,秘密不应与应用程序一起部署)、用户名和密码来调用授权服务器的令牌端点
- 授权服务器检查用户名和密码(通过任何方式,你知道故事)并决定范围(...)
- AS 再次通过管理 API 与 Kong 对话,为提供的
client_id 获取 client_secret,为所需 API 获取 provision_key
-
AS 向 Kong 的令牌端点 [/your_api]/oauth2/token 发出调用,如下所示:
curl --insecure -d 'grant_type=password&provision_key=<...>&client_id=<...>&client_secret=<...>&authenticated_userid=<...>&scope=' https://:8443/ your_api/oauth2/token
请注意,此调用不包含用户名和密码;那些不属于这里的,你必须根据你自己的身份来源检查用户名和密码,Kong 不会帮你的。
此调用应返回访问令牌和刷新令牌,然后您将它们(尽可能安全地)存储在您的设备上。这些替换用户名和密码,不得存储在设备上。访问令牌可以与其他最终用户上下文流(授权代码授予、隐式授予)一样用于代表经过身份验证的用户访问 API。
将 Kong 与 OAuth2 一起使用是棘手且复杂的,但 Kong 确实可以帮助您正确处理并分离您的顾虑。