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

标签 node.js firebase firebase-authentication jwt firebase-admin

我正在一个项目中,我们将在微服务体系结构中使用不同的服务,并且我们还希望使用一些Firebase服务。我正在使用要在Firebase和其他API项目中使用的自定义JWT的身份验证服务器。

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


用户使用客户端上的收藏夹提供程序登录
如果登录成功,则用户将从Firebase收到JWT。这被发送到身份验证服务器进行验证
如果身份验证服务器可以使用admin SDK验证令牌,请创建一个包含更多数据的新自定义令牌,然后将此新的自定义令牌返回给客户端
让客户端使用新的自定义令牌重新进行身份验证,并将其用于与Firebase和我们的其他API项目(主要在.NET Core中)进行通信


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

TL; DR:此处有两个问题:


验证使用Firebase Node.JS Admin SDK发行的自定义令牌时,应使用什么作为公钥?是从Google公开的JWK中提取的密钥,还是从用于签名的私钥中提取的密钥?
如果采用JWK方法,应如何使用kid标头构造自定义令牌?




首先,我对验证的正确方法感到怀疑。 (请原谅,创建OAuth流不是我的经验。)所使用的算法是RS256,因此我应该能够使用公钥来验证令牌。如我所见,有两种方法可以获取此密钥:


从私钥中提取公钥并进行验证。我可以执行此操作,并在我的身份验证服务器上的测试端点上成功验证,但是我认为这是错误的方法
我认为的另一种更正确的方法是使用令牌中的值在我的项目的Google“ /。well-known / openid-configuration /”端点上找到JWK,即


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

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

通过执行以下操作从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),这导致两个选项之一:


使用上面的第一种方法。但是,这会导致问题-如果我出于某种原因需要撤消或重置身份验证服务器上的私钥,则需要这样做并将更改也部署到所有其他服务上,从而使解决方案的动态性降低并且更容易出错。
使用jwt.io中提到的一个库手动生成类似的令牌,然后将原始Firebase ID令牌中的kid添加到其标头中。


问题2:


那么,我应该把ass,aud和sub放在什么位置呢?与admin SDK具有相同的值吗?如果是这样,那不是“作弊”,因为他们不再是发行人了吗?
我已经尝试过了(生成了类似的令牌副本,但是添加了原始令牌的kid),而且我似乎无法使用为孩子创建的PEM密钥来验证生成的令牌。


我做后者的方法是这样(在主题上跟随blog guide):


转到https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com并获取相关孩子的模数(n)和指数(e)
使用lib(rsa-pem-from-mod-exp)生成公共密钥
使用密钥验证是否使用the 'official' jwt lib

上面的结果是这样的公钥:

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


似乎有两件事是错误的。一种是密钥不同于我可以从私钥中提取的密钥。另一个是我从私钥中提取的内容具有以下注释:

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


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

最后,我是否完全误解了OpenID流?是否还需要我的私钥生成JWK来验证我的JWT?我是否应该在身份验证服务器上公开自己的JWK,以便其他服务代替Google来联系和使用?我对Firebase Admin SDK可以做什么和不可以做什么感到困惑,我认为:-)

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

我在研究中依赖的一些资源(当然还有官方的sdk docs文档):


jwt.io
Is it still possible to do server side verification of tokens in Firebase 3?
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/

最佳答案

在使用自定义令牌对Firebase客户端SDK重新进行身份验证之后,客户端实际上会使用自定义令牌中的声明生成一个新的ID令牌。该ID令牌是您用来验证对不同微服务的请求(记录为here)的工具。因此,可以,您原来的ID令牌将被丢弃,但是会在其位置创建一个新的令牌。并且该ID令牌将每小时自动刷新一次。因此,只要需要,您就应该能够调用user.getToken()以获得有效的ID令牌。该方法代表您处理所有缓存。

关于node.js - Firebase Admin SDK的Node.js身份验证服务器-JWT验证问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42560558/

相关文章:

javascript - 尝试仅添加到用户时不断获得缺少的权限

angularjs - Firebase:如何从两个节点查询不重叠的数据?

firebase - 在 beta 0.3.2 : incompatible block pointer 上使用 Firebase-auth 插件的 Flutter 的 Xcode 构建错误

swift - 能够在 Firebase 中对用户进行身份验证,但无法将用户数据存储在 Firebase 数据库中

firebase - Firebase不会返回用户

javascript - 你如何在 node.js 应用程序中提供 CSS

node.js - Socket.io 发出的信号并不总是在 Node.js + Redis + Heroku(多测功机)环境中收到

javascript - MySQL连接错误node.js events.js 182

javascript - $firebase 在 AngularJS 中未定义

node.js - node-schedule 有时不工作