Node.js Firebase Admin SDK 的身份验证服务器 - JWT 验证问题

Node.js authentication server for Firebase Admin SDK - JWT validation issue

我正在做一个项目,我们将在微服务架构中使用不同的服务,我们还想使用一些 Firebase 服务。我正在开发一个身份验证服务器,该服务器将创建自定义 JWT 以用于 Firebase 以及其他 API 项目。

我们想使用 Firebase Auth SDK 轻松与 FB、Google、Twitter 等集成,但我们需要用更多数据丰富用户的令牌。因此,我的想法是创建一个 Node.JS 身份验证服务器,它使用 Firebase Admin SDK 来执行此操作。流程如下:

  1. 用户在客户端使用最喜欢的提供商登录
  2. 如果登录成功,用户会收到来自 Firebase 的 JWT。这被发送到 auth 服务器进行验证
  3. 如果授权服务器可以使用管理 SDK 验证令牌,则创建一个包含更多数据的新自定义令牌,然后 return 将此新自定义令牌发送给客户端
  4. 让客户端 re-authenticate 使用新的自定义令牌,并使用它与 Firebase 以及我们的其他 API 项目(主要在 .NET Core 中)进行通信

步骤 1-3 工作正常。 尝试在其他服务上验证自定义令牌时出现问题

TL;DR : 这里有两个问题:

  1. 验证使用 Firebase Node.JS Admin SDK 发出的自定义令牌时,我应该使用什么作为 public 密钥?从 Google 公开的 JWK 中提取的密钥,或从用于签名的私钥中提取的密钥?
  2. 如果是 JWK 方法,我应该如何使用 kid header 构造自定义令牌?

首先,我对验证它的正确方法存有疑问。 (请原谅,我没有创建 OAuth 流程的经验。)使用的算法是 RS256,所以我应该能够使用 public 密钥验证令牌。据我所知,有两种方法可以获取此密钥:

  1. 从私钥中提取 public 密钥并使用它进行验证。我可以这样做并在我的身份验证服务器上的测试端点上成功验证,但是我觉得这是不正确的方法
  2. 另一种我认为更正确的方法是使用令牌中的值在我的项目的 Google 的“/.well-known/openid-configuration/”端点上找到 JWK, , 即

https://securetoken.google.com/[项目 ID]/.well-known/openid-configuration

检索正确 kid(密钥 ID)的指数和模数并从中创建 public 密钥。

admin SDK通过

生成的token
admin.auth().createCustomToken(uid, additionalClaims).then(function(customToken)

一些自定义声明看起来像这样:

headers:

{
  "alg": "RS256",
  "typ": "JWT"
}

有效负载:

{
  "claims": {
    "premiumAccount": true,
    "someRandomInnerObject": {
      "something": "somethingRandom"
    }
  },
  "uid": "<uid for the user>",
  "iat": 1488454663,
  "exp": 1488458263,
  "aud": "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
  "iss": "firebase-adminsdk-le7ge@<PROJECT ID>.iam.gserviceaccount.com",
  "sub": "firebase-adminsdk-le7ge@<PROJECT ID>.iam.gserviceaccount.com"
}

不过,我似乎无法使用方法 2。一个问题是 生成的令牌没有 kid header,因此不符合 OpenID规范(AFAIK),这导致两个选项之一:

  1. 使用上面的第一种方法。但这会导致问题 - 如果我出于某种原因需要撤销或重置身份验证服务器上的私钥,我需要这样做并将更改也部署到所有其他服务上,从而使解决方案的动态性降低并且更多 error-prone.
  2. 使用 jwt.io 中提到的库之一手动生成类似的令牌,并将原始 Firebase ID 令牌中的孩子添加到它的 headers。

数字 2 有问题:

我做后者的方式是这样的(遵循关于这个主题的blog guide):

  1. 转到 https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com 并检索相关孩子的模数 (n) 和指数 (e)

  2. 使用库生成 public 密钥 (rsa-pem-from-mod-exp)

  3. 使用密钥验证使用the 'official' jwt lib

    上面的结果是 public 键:

    -----开始 RSA PUBLIC 密钥----- MIIBCgKCAQEAxXpo7ChLMnv1QTovmm9DkAnYgINO1WFBWGAVRt93ajftPpVNcxMT MAQI4Jf06OxFCQib94GyHxKDNOYiweVrHVYH9j/STF+xbQwiPF/8L7+haC2WXMl2 tkTgmslVewWuYwpfm4CoQFV29OVGWCqwEcbCaycWVddm1ykdryXzNTqfzCyrSZdZ k0yoE0Q1GDcuUl/6tjH1gAfzN6c8wPvI2YDhc5gIHm04BcLVVMBXnC0hxgjbJbN4 zg2QafiUpICZzonOUbK6+rrIFGfHpcv8mWG1Awsu5qs33aFu1Qx/4LdMAuEsvX9f EmFZCUS8+trilqJbcsd/AQ9eOZLAB0BdKwIDAQAB -----结束 RSA PUBLIC 密钥-----

有两点似乎不对。一是密钥与我从私钥中提取的密钥不同。另一个是我从私钥中提取的那个有这些注释:

-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----

没有 'RSA'。这有关系吗?无论如何,它不验证。

终于,我是不是完全误解了OpenID流程? JWK 是否是从我需要的私钥生成的,以验证我的 JWT?我应该暴露我的在我的身份验证服务器上拥有 JWK,以便其他服务联系和使用而不是 Google?我对 Firebase Admin SDK 能做什么和不能做什么感到有点困惑,我想 :-)

我知道有很多问题,但我认为它们都是相关的。

我在研究中依赖的一些资源(当然除了官方的 admin sdk 文档):

使用自定义令牌重新验证 Firebase 客户端 SDK 后,客户端实际上生成了一个新的 ID 令牌,其中包含来自自定义令牌的声明。您应该使用此 ID 令牌来验证对不同微服务发出的请求(已记录 here). So yes, your original ID token is discarded, but a new one is created in its place. And that ID token will be automatically refreshed every hour. So, you should be able to just call user.getToken() 以在您需要时获取有效的 ID 令牌。该方法代表您处理所有缓存。