如何在不同的API之间验证JSON Web Tokens(JWT)?

6

我创建了一个基于PHP Slim框架的Rest API,使用JSON Web Tokens(JWT)进行身份验证和授权。

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

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

问题是,如何对JWT进行身份验证,因为API没有访问用于生成它的密钥?

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

由于每个API和新的身份验证服务都将在同一主机上运行,因此我可以在它们之间共享密钥,但这感觉不是一个好的做法。有更好的方法吗?

2个回答

4
最好使用私钥/公钥(RSA或ECDSA算法)来签署JWT,而不是使用密钥(HMAC算法)。在这种情况下,您的身份验证服务将使用私钥签署JWT,其他API将使用公钥验证JWT,当然...您仍然需要向API分发公钥,但您有选择。
根据您的架构,您可能需要考虑以下内容: API网关模式 对于微服务架构,一个好的实践是使用API网关模式。 更多关于网关模式的信息。API网关可以验证JWT令牌,然后代理请求到您的服务。因此,身份验证服务将使用私钥签署JWT令牌,然后请求将通过API网关进行。API网关将使用公钥验证令牌,因此您不需要将公钥分发给代理后面的所有API。
使用这种方法,您需要一个API网关,您可以查看:express-gateway, kong + jwt plugin, tyk等等。此外,API网关有很多其他好处,而不仅仅是JWT令牌验证,例如流量控制、分析、日志记录、请求和响应转换等。 密码管理 除了或者附加到API网关之外,您还可以查看集中式密码管理系统,例如Hashi Vault。根据项目/团队的大小,这可能对您的项目来说过于复杂了。

1
可以用来生成消息认证码(MAC)或数字签名的加密算法列在RFC 7518中。
在所有算法的列表中,唯一“必须”由符合规范的实现实施的算法是使用SHA256的HMAC(HS256)。HS256需要一个私有密钥来签署令牌以及验证令牌。如果您正在使用HS256,则理想情况下不应将密钥共享在所有服务器之间。相反,签名和验证逻辑都将保留在“授权服务器”中(OAuth2术语)。单个的“资源服务器”(同样是OAuth2术语)将调用授权服务器中的服务来验证令牌。但是,每次API调用都调用授权服务器令牌验证API可能不切实际。因此,对于资源服务器来说,将JWT缓存起来,并将传入请求中的JWT与缓存的JWT列表进行比较可能是一个好主意。如果缓存中不存在传入的JWT,则只会调用授权服务器验证功能。这确保了不需要共享秘密签名密钥,并且也不会为每个API调用调用远程授权服务器验证函数。
RFC中推荐的另外两个算法是“RSASSA-PKCS1-v1_5使用SHA-256”和“ECDSA使用P-256和SHA-256”(ES256),后者(ECDSA)很可能在未来也会成为“必需”的。
如果您使用ES256,则应将私钥保留在授权服务器以用于签署令牌,并在所有资源服务器之间共享公钥,以便每个资源服务器都可以使用公钥验证签名。这确实节省了资源服务器进行验证的授权服务器调用的成本,而无需与每个资源服务器共享密钥。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接