如何跨不同 API 对 JSON Web 令牌 (JWT) 进行身份验证?

Posted

技术标签:

【中文标题】如何跨不同 API 对 JSON Web 令牌 (JWT) 进行身份验证?【英文标题】:How to authenticate JSON web tokens (JWT) across different APIs? 【发布时间】:2019-08-19 01:34:19 【问题描述】:

我创建了一个基于 php Slim 框架的 Rest API,它使用 JSON Web 令牌 (JWT) 来验证和授权访问。

要使用 API,客户端必须首先通过将其凭据发送到特殊的 /auth/token 路由来验证自己,如果正确,则返回包含允许权限列表的数字签名令牌。对 API 的所有后续请求都需要令牌进行身份验证和授权。这是非常标准的东西,效果很好。

但现在我想将/auth/token 服务分离到自己的微服务中,以便将来与其他 API 一起重用它。

问题是,API 现在将如何验证 JWT,因为它们无法访问用于生成 JWT 的密钥?

我使用Firebase\JWT\JWT 生成令牌,该令牌将被移至新的身份验证服务。我使用tuupola/slim-jwt-auth 中间件对每个API 上接收到的令牌进行身份验证。

由于每个 API 和新的身份验证服务都将在同一台主机上运行,​​我也许可以在它们之间共享秘密,但这感觉像是不好的做法。有没有更好的办法?

【问题讨论】:

【参考方案1】:

最好使用私钥/公钥(RSA 或 ECDSA 算法)而不是秘密(HMAC 算法)来签署 JWT。在这种情况下,您的身份验证服务将使用私钥签署 JWT,而其他 API 将使用公钥验证 JWT,嗯……您仍然需要向您的 API 分发公钥,但您可以选择。

取决于您的架构,您可能会查看:

API 网关模式

对于微服务架构,一个好的做法是使用 API 网关模式。 More about gateway pattern。 API Gateway 可以验证 JWT 令牌,然后将请求代理到您的服务。因此身份验证服务将使用私钥签署 JWT 令牌,然后对 API 的请求将通过 API 网关。 API Gateway 将使用公钥验证令牌,因此您不会将公钥分发给代理后面的所有 API。

使用这种方法,您需要一个 API 网关,您可以查看:express-gateway、kong + jwt plugin、tyk 等,API 网关还有更多好处,而不仅仅是 JWT 令牌验证,如流量控制、分析、日志记录、请求和响应转换等。

秘密管理

除了 API Gateway 之外,您还可以查看集中式机密管理系统,例如 Hashi Vault。取决于项目/团队的规模,这对您的项目来说可能是多余的。

【讨论】:

【参考方案2】:

RFC 7518 中列出了可用于生成消息验证码 (MAC) 或数字签名的加密算法。

在整个算法列表中,唯一“需要”由兼容实现实现的算法是使用 SHA256 (HS256) 的 HMAC。 HS256 需要一个私有密钥来签署令牌以及验证令牌。如果您使用的是 HS256,理想情况下您不应该在所有服务器之间共享密钥。相反,签名和 tge 验证逻辑都将保留在“授权服务器”(OAuth2 术语)中。单独的“资源服务器”(同样是 OAuth2 术语)将调用授权服务器中的服务来验证令牌。但是,为每个 api 调用调用授权服务器令牌验证 api 可能不切实际。因此,资源服务器缓存 JWT 并简单地将传入请求中的 JWT 与缓存的 JWT 列表进行比较可能是一个好主意。如果传入的 JWT 不存在于缓存中,那么只会调用授权服务器验证功能。这样可以确保不需要共享秘密签名密钥,并且也不会为每个 api 调用调用远程授权服务器验证函数。

RFC 中另外两种推荐的算法是“使用 SHA-256 的 RSASSA-PKCS1-v1_5”和“使用 P-256 和 SHA-256 的 ECDSA”(ES256),其中后者(ECDSA)很可能也是将来成为“必需”。

如果您使用 ES256,您需要将私钥与授权服务器一起保存以对令牌进行签名,并在所有资源服务器之间共享 tge 公钥,以便每个资源服务器都可以使用公钥验证签名。这无疑使资源服务器免于以增加计算为代价进行授权服务器调用以进行验证,并且不必与每个资源服务器共享密钥。

【讨论】:

如果我不能使用公钥/私钥(tuupola/slim-jwt-auth 似乎不支持它),让“授权服务器”来创建和验证令牌的想法非常相似。我应该能够创建一个中间件层来对每个路由应用验证。

以上是关于如何跨不同 API 对 JSON Web 令牌 (JWT) 进行身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

使用 JWT(JSON Web 令牌)设置令牌到期的 RESTful API

如何在 Django 和 Python 中使用 JWT(JSON Web 令牌)来创建用于注册和登录的 REST API

如何从外部应用程序安全地使用json web令牌,与wordpress rest api对话

如何在 Asp.NET Core WEB API 中使用 .Net (C#) 在 Payload 中创建具有自定义 JSON 声明的 JWT 令牌

Web Api中的JSON Web令牌与承载令牌

如何在 ASP.NET Core Web API 中添加两个不同的令牌