当开发使用OAuth2/客户端凭据auth相互调用的微服务时,其中服务有自己的凭据,我经常发现自己正在编写代码:
- 用静态
client_id
和client_secret
交换有时间限制的JWT承载令牌 - 对许多请求多次使用该令牌,直到其过期(或即将过期(
- 获取新令牌,然后重复
考虑到缓存是计算机科学中的两个难题之一(以及命名和逐个错误(,我希望能够找到一个已经做到这一点的库,或者如果做不到这一点,就写一个。
功能愿望清单:
- 底层非阻塞http客户端
- 用户可以配置一次有关身份验证的详细信息,然后不必在每次发出api请求时都考虑它
- 用户可以使用它来调用任何任意的api
- 在编写了定义api端点/模型等的代码后,有一些简单的方法,如
.invokeWithAuth
或其他可以处理请求令牌(如果需要(或向请求添加有效令牌(如果缓存(的方法 - 除了请求量非常低的情况外,大多数请求都应该使用缓存的令牌,而不是为每个请求请求一个新的令牌
- 该库应该具有管理令牌过期的有效方法,比如使用新令牌重试处理401响应,或者在令牌过期之前抢先刷新令牌
- 库应该能够从令牌响应中确定(可能通过用户实现的接口(特定令牌的有效期
我很乐意找到一个能做其中一些的库,但我没有成功。有人知道或使用过一个能很好地解决这个问题的图书馆吗?还有其他我忽略的解决方案吗?我可以编写代码来完成这一切,但我可能会错过一些边缘情况。
我实际上是在用scala编写代码,所以scala库甚至比java库更好,但java库完全可以从scala中使用。
这是一个重要的问题,尽管并没有真正的一刀切的解决方案。我肯定会致力于开发一个可以在微服务之间共享的实用程序客户端库,以进行常见的安全性和可靠性处理。
通用要求
- 不同的OAuth流
- 401次重试
- 同步令牌刷新
- 令牌缓存
- 用于记录和关联的标头
- 一致超时
- 一致的错误和日志记录
- 处理不可用性,如断路器
可能的方法
我喜欢定义两种类型的类作为service agents
,前者使用后者。这将应用程序其他部分的代码简化为一行代码。以下是我的Android应用程序中的一些Kotlin代码:
- ApiClient
- OAuthClient
在公司设置中,我也会以可共享的方式考虑共享的fetch
逻辑。
API简化
出于兴趣,来自同一公司的微服务通常可以相互转发JWT,同时仍然确保零信任架构。关于范围的文章最佳实践对此进行了解释。
优点:
- 更简单的代码,因为微服务只需要充当资源所有者,而不需要充当OAuth客户端
- 以安全的方式维护原始调用程序,并避免可能的不安全做法,例如在自定义标头中传递用户ID
- 授权服务器上的负载更少,需要管理的客户端更少
例如,上面的Android客户端调用这个Java API,它只验证JWT,不需要获取或缓存令牌。
在组织边界内,如果只有UI是OAuth客户端,它有时可以工作得最好。作用域检查可防止API之间明显无效的调用。
如果需要,基础设施安全性(如Kubernetes网络策略(可以进一步锁定机器到机器的连接,这比许多客户端ID和机密更容易管理。
摘要
这些只是基于我自己的经验的一些想法。