我已经基于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和新的身份验证服务都将在同一主机上运行,因此我可能会在它们之间共享秘密,但这是一种不好的做法。有更好的方法吗?
答案 0 :(得分:1)
最好使用私钥/公钥(RSA或ECDSA算法)而不是秘密(HMAC算法)对JWT进行签名。在那种情况下,您的身份验证服务将使用私钥对JWT进行签名,而其他API将使用公钥对JWT进行验证,那么……您仍然需要向其API分配公钥,但是您可以选择。
取决于您的体系结构,您可以查看:
API网关模式
对于微服务架构,一个好的实践是使用API网关模式。 More about gateway pattern。 API网关可以验证JWT令牌,然后将请求代理到您的服务。因此,身份验证服务将使用私钥对JWT令牌进行签名,然后对API的请求将通过API网关发送。 API Gateway会使用公共密钥验证令牌,因此您不会将公共密钥分发给代理后面的所有API。
使用这种方法,您将需要一个API网关,您可以查看:express-gateway,kong + jwt plugin,tyk等,此外,还有很多好处API网关,而不是JWT令牌验证,例如流量控制,分析,日志记录,请求和响应转换等。
秘密管理
除了API网关外,您还可以查看集中式机密管理系统,例如Hashi Vault。取决于项目/团队的规模,这可能对您的项目来说是一个过大的杀伤力。
答案 1 :(得分:1)
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公钥,以便每个资源服务器都可以使用公钥来验证签名。这无疑可以节省资源服务器以增加计算为代价而不必授权服务器调用验证的费用,而不必与每个资源服务器共享秘密。