验证 JWT 令牌签名

Posted

技术标签:

【中文标题】验证 JWT 令牌签名【英文标题】:Verify JWT Token Signature 【发布时间】:2019-11-01 22:47:52 【问题描述】:

我目前正在使用 Vapor 开发 Swift 后端。我的 ios 客户端使用新的 iOS 13 功能“使用 Apple 登录”。当用户登录时,我得到一个身份令牌(访问令牌),它是由 Apple 签名的有效 JWT 令牌。这将在所有正在进行的通信中发送到服务器,以验证服务器提供的某些路由。

在服务器上,我想通过验证令牌签名来验证发送的令牌确实是由 Apple 签名的,并且不是由某些恶意用户专门制作的。 Apple 提供了一个 HTTP 端点来检索公钥来执行此操作:Apple Documentation。

但是我不确定我必须多久查询一次此端点以从 API 检索模数和指数并构建公钥然后验证签名。 查询一次并将公钥存储在服务器上以使用它是否足够,或者我需要在验证签名之前查询中间件中的 HTTP 端点(对于每个受保护的路由)?

基本上我不确定模数和指数是否会不时改变。

【问题讨论】:

jwt.io 列出了所有流行语言的 JWT 验证库。 为什么要更改公钥? @user28434 我知道如何验证签名,我不确定公钥可能多久更改一次。 @LutzHorn 我不确定。由于密钥不在我的控制范围内,我想谨慎行事,因为当密钥更改时,我的服务器将不再工作,因为无法验证所有令牌。但是,如果我只能生成一次密钥并在我的服务器上使用它,那就太棒了,因为这意味着没有不必要的 http 请求并减少了我的开销。 如果你使用苹果服务,你必须使用他们的公钥。那么“生成一次密钥”是什么意思?如果您不控制发布 JWT 的服务,您就无法控制密钥。 【参考方案1】:

你可以这样做:

获取一次公钥,将其存储在您的服务器上 请求进来,尝试使用存储的公钥验证签名 如果失败,再次获取公钥并存储它 再次尝试验证签名

这将使您能够在必要时立即了解更改的公钥。

【讨论】:

这显然是解决问题的好方法。非常感谢:) 再补充一点,假设有十个用户的 JWT1 使用 key1 签名。然后苹果将他们的密钥更改为 key2。然后说其他十个用户使用 key2 签署了他们的 JWT2(此时您的系统中仍然有 key1)。现在假设用户使用 JWT2,那么您的验证将失败,您将从苹果获取公钥并重试,这将检查出来。现在假设有 10 个用户向您发送 JWT1,这意味着您最终会从苹果获取 10 次并且每次都失败。因此,您可能希望将从苹果获得的所有各种密钥存储在数据库本身中

以上是关于验证 JWT 令牌签名的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft 帐户 JWT 身份验证令牌如何签名?

JWT/OAuth 令牌签名验证失败

使用 java-jwt 验证访问令牌签名

如何验证在 jwt.io 上使用 Keycloak 身份验证提供程序创建的 HS256 签名 JWT 令牌

如何在 Nimbus JOSE + JWT 中验证令牌签名

为啥 openssl_verify() 无法验证我的 JWT 令牌签名?