用于Firebase Admin SDK的Node.js身份validation服务器 – JWTvalidation问题

我正在开发一个项目,我们将在微服务架构中使用不同的服务,同时我们也希望使用一些Firebase服务。 我正在开发一个auth服务器,这个服务器将用于在Firebase以及其他API项目中使用自定义JWT。

我们希望使用Firebase Auth SDK轻松地与FB,Google,Twitter等进行整合,但是我们需要用更多的数据来丰富用户的令牌。 因此,我的思考过程是创build一个使用Firebase Admin SDK的Node.JS auth服务器来执行此操作。 stream程如下:

  1. 用户使用客户端上的collections提供程序login
  2. 如果login成功,用户将从Firebase收到JWT。 这被发送到auth服务器进行validation
  3. 如果auth服务器可以使用admin SDKvalidation令牌,则创build一个新的自定义令牌,并添加更多数据,然后将此新自定义令牌返回给客户端
  4. 让客户端使用新的自定义令牌重新进行身份validation,并将其用于与Firebase以及我们的其他API项目(主要在.NET Core中)进行通信。

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

TL; DR :有两个问题:

  1. 在validation使用Firebase Node.JS Admin SDK发布的自定义令牌时,我应该使用什么作为公钥? 从Google公开的JWK中提取的关键字,还是从用于签名的私钥中提取的密钥?
  2. 在JWK方法的情况下,我应该如何构build一个kid头自定义令牌?

首先,我怀疑validation它的正确方法。 (请原谅,我没有那么有经验的创buildOAuthstream。)使用的algorithm是RS256,所以我应该能够使用公钥validation令牌。 正如我所看到的,有两种方法来获得这个关键:

  1. 从私钥中提取公钥并使用它进行validation。 我可以在auth服务器上的testingterminal上成功地进行validation,但是我觉得这是不正确的做法
  2. 另一种更正确的方法是使用令牌中的值在我的项目的Google的“/.well-known/openid-configuration/”端点上查找JWK,即

https://securetoken.google.com/[PROJECT ID] /。well-known / openid-configuration

检索正确的kid (密钥ID)的指数和模数,并从这些中创build公钥。

从admin SDK生成的令牌

 admin.auth().createCustomToken(uid, additionalClaims).then(function(customToken) 

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

标题:

 { "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 ,因此不符合OpenID规范(AFAIK),这导致了以下两种select之一:

  1. 用上面的第一种方法。 这会导致问题 – 如果由于某种原因需要撤销或重置auth服务器上的私钥,则需要执行此操作,并将更改部署到所有其他服务上,从而使解决scheme的dynamic性更低,更容易出错。
  2. 使用jwt.io中提到的某个库手动生成类似的令牌,并将原始Firebase ID令牌中的孩子添加到其标头中。

问题2:

  • 那么我应该把什么作为iss,aud和sub呢? 与pipe理SDK相同的值呢? 如果是这样,是不是“作弊”,因为他们不再是发行人?
  • 我试过了(生成一个类似的令牌副本,但添加了原始令牌的kid ),我似乎无法validation使用创build的孩子的PEM密钥生成的令牌。

我做后者的方式是这样的(关于这个主题的博客指南 ):

  1. 请访问https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com ,检索相关孩子的模数(n)和指数(e)
  2. 使用lib( rsa-pem-from-mod-exp )生成公钥
  3. 使用密钥来validation使用“官方”的jwt库

    以上结果是公钥:

    —– BEGIN RSA公钥—– MIIBCgKCAQEAxXpo7ChLMnv1QTovmm9DkAnYgINO1WFBWGAVRt93ajftPpVNcxMT MAQI4Jf06OxFCQib94GyHxKDNOYiweVrHVYH9j / STF + xbQwiPF / 8L7 + haC2WXMl2 tkTgmslVewWuYwpfm4CoQFV29OVGWCqwEcbCaycWVddm1ykdryXzNTqfzCyrSZdZ k0yoE0Q1GDcuUl / 6tjH1gAfzN6c8wPvI2YDhc5gIHm04BcLVVMBXnC0hxgjbJbN4 zg2QafiUpICZzonOUbK6 + rrIFGfHpcv8mWG1Awsu5qs33aFu1Qx / 4LdMAuEsvX9f EmFZCUS8 + trilqJbcsd / AQ9eOZLAB0BdKwIDAQAB —– END RSA公共密钥— –

有两件事情似乎是错的。 一个是关键不同于我可以从私钥中提取的关键。 另一个是我从私钥中提取的那个有这些注释:

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

没有“RSA”。 这很重要吗? 无论如何,它不validation。

最后 ,我是否完全误解了OpenIDstream? JWK是否还需要私钥才能validation我的JWT? 我是否应该在自己的auth服务器上公开自己的JWK,以便其他服务可以联系并使用,而不是使用Google的? 我对Firebase Admin SDK做了什么和不做什么感到困惑,我想:-)

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

我在研究中所依赖的一些资源(除了官方的sdk docs of course):

  • jwt.io
  • Firebase 3中是否还可以对令牌进行服务器端validation?
  • https://ncona.com/2015/02/consuming-a-google-id-token-from-a-server/
  • https://stackoverflow.com/a/42410233/1409779
  • https://andrewlock.net/a-look-behind-the-jwt-bearer-authentication-middleware-in-asp-net-core/

在使用自定义令牌重新validationFirebase客户端SDK之后,客户端实际上会生成一个新的ID令牌,其中包含来自自定义令牌的声明。 此ID令牌是您应该用来validation对不同的微服务(请参阅此处logging )的请求。 所以是的,你的原始ID令牌被丢弃了,但是在它的位置上创build了一个新的ID令牌。 那个ID令牌将会每小时自动刷新一次。 所以,只要你需要,你应该能够调用user.getToken()来获得一个有效的ID标记。 该方法代表您处理所有的caching。