简体   繁体   English

Firebase currentUser.getIdToken() 在 signInWithCustomToken 之后返回自定义令牌

[英]Firebase currentUser.getIdToken() returns custom token after signInWithCustomToken

I'm debugging session timeout issues on a Next.js WEB/Node app that uses Firebase Auth for sign in. I am leveraging custom tokens for granular firestore security rules.我正在调试 Next.js WEB/Node 应用程序上的 session 超时问题,该应用程序使用 Firebase Auth 进行登录。我正在利用自定义令牌进行粒度 Firestore 安全规则While debugging, I'm finding that the idToken I send to the backend to create the custom token appears to be a custom token itself after the initial client call.在调试时,我发现在初始客户端调用之后,我发送到后端以创建自定义令牌的 idToken 本身似乎是一个自定义令牌。 At the very least it contains my custom claims and so far as I understand from the docs, the server can only deal with idTokens as per the glaring red notice at https://firebase.google.com/docs/auth/admin/verify-id-tokens .至少它包含我的自定义声明,据我从文档中了解到,服务器只能根据https://firebase.google.com/docs/auth/admin/verify 上的明显红色通知处理 idToken -id-令牌 I don't know if this is the source of the timeout errors, but it seems peculiar.我不知道这是否是超时错误的根源,但这似乎很奇怪。

Update更新

While investigating why the picture field was not present on the decoded tokens, I discovered that the first argument to createCustomToken was incorrectly the firestore doc id of the user collection doc rather than the id token's uid field.在调查为什么解码后的令牌上不存在picture字段时,我发现createCustomToken的第一个参数错误地是用户集合文档的 firestore doc id,而不是 id 令牌的uid字段。 All the same clarifying questions apply still.所有相同的澄清问题仍然适用。 However, I'm hoping this misstep addresses things.但是,我希望这个失误能解决问题。 It made the picture field return on the subsequent decodings of the token.它使picture字段在令牌的后续解码中返回。 However, the token still has my custom claims which may or may not be an issue still.但是,令牌仍然有我的自定义声明,这可能仍然是问题,也可能不是问题。

Initial Login初始登录

Web Client code Web 客户端代码

signInResult = await firebase.auth().signInWithPopup(googleProvider);
//... exception handling ...
const { user } = signInResult;
const fbToken = await user.getIdToken();
// axios POST request to backend with fbToken in data payload

Backend Code using FB Admin client使用 FB Admin 客户端的后端代码

decodedToken = await adminClient.auth().verifyIdToken(data.fbIdToken);
//... validation and exception handling ...
// . If I log out decodedToken:
{ name: 'Blaine Garrett',
  picture: '...',
  iss: '...',
  aud: '...',
  auth_time: 1569160850,
  user_id: '...',
  sub: '...',
  iat: 1569160850,
  exp: 1569164450,
  email: '...',
  email_verified: true,
  firebase:
   { identities: { 'google.com': [Array], email: [Array] },
     sign_in_provider: 'google.com' },
  uid: '...' }
{ issued: 2019-09-22T14:00:50.000Z,
  expires: 2019-09-22T15:00:50.000Z }


let userId = decodedToken.uid; // As per update, this was not the case originally

// Build custom claims
customToken = await adminClient.auth().createCustomToken(userId, additionalClaims);
// return customToken in a 200 response

On the client in the response from server在来自服务器的响应中的客户端

...
await firebase.auth().signInWithCustomToken(customToken);
...

Subsequent Calls If I then call const firebaseIdToken = await firebase.auth().currentUser.getIdToken();后续调用如果我再调用const firebaseIdToken = await firebase.auth().currentUser.getIdToken(); after the above signInWithCustomToken and send that result to the backend and log the token, the decoded token is:在上述signInWithCustomToken并将结果发送到后端并记录令牌之后,解码的令牌是:

{ email: '...',
  user_roles: [ 'admin', 'support' ], // <-- my custom claims
  iss: '...',
  aud: '...',
  auth_time: 1569161153,
  user_id: '...',
  sub: '...',
  iat: 1569161163,
  exp: 1569164763,
  firebase: { identities: {}, sign_in_provider: 'custom' },
  uid: '...' }
{ issued: 2019-09-22T14:06:03.000Z,
  expires: 2019-09-22T15:06:03.000Z }
// Note: not everything is present on this token, including `picture` property and `email_verified`, etc

So even though I call currentUser.getIdToken() on the client, it appears to be my custom token - or at least have my custom claims and some of the original id token fields missing.因此,即使我在客户端调用currentUser.getIdToken() ,它似乎是我的自定义令牌 - 或者至少有我的自定义声明和一些原始 id 令牌字段丢失。

  1. Is that expected behavior?这是预期的行为吗? ie getIdToken will return the custom token if signInWithCustomToken was previously called.即如果之前调用了signInWithCustomToken,getIdToken 将返回自定义令牌。

  2. Is it valid to attempt to use verifyIdToken on the server if the given token is a custom token?如果给定令牌是自定义令牌,尝试在服务器上使用 verifyIdToken 是否有效?

  3. Is that actually a customToken or does FB just preserve the claims.这实际上是一个 customToken 还是 FB 只是保留了声明。 (the missing profile field confuses me). (缺少的个人资料字段让我感到困惑)。

  4. Is there a way to differentiate a custom token from an idToken?有没有办法区分自定义令牌和 idToken?

  5. Per update above What's the purpose of being able to send any arbitrary value for the first argument of createCustomToken?根据上述更新,能够为 createCustomToken 的第一个参数发送任意值的目的是什么? eg.例如。 I passed asdf and the token was minted fine and subsequently decoded fine.我通过了asdf并且令牌被很好地铸造并且随后被很好地解码。 Would this have an effect of session timeout?这会影响 session 超时吗?

Thanks for any insight.感谢您的任何见解。 Again, I don't know if this is the source of my timeout issues, but I ran across this trying to debug and it made me question my understanding of the documentation.同样,我不知道这是否是我的超时问题的根源,但我在尝试调试时遇到了这个问题,这让我质疑我对文档的理解。

When you add custom claims to a Firebase Authentication user account, they are not immediately "visible" to the client until their ID token refreshes somehow.当您向 Firebase 身份验证用户帐户添加自定义声明时,它们不会立即对客户端“可见”,直到它们的 ID 令牌以某种方式刷新。 This behavior is documented :这种行为记录在案

After new claims are modified on a user via the Admin SDK, they are propagated to an authenticated user on the client side via the ID token in the following ways:在通过管理员 SDK 对用户修改新声明后,它们会通过 ID 令牌以下列方式传播到客户端的经过身份验证的用户:

  • A user signs in or re-authenticates after the custom claims are modified.修改自定义声明后,用户登录或重新验证。 The ID token issued as a result will contain the latest claims.结果颁发的 ID 令牌将包含最新的声明。
  • An existing user session gets its ID token refreshed after an older token expires.现有用户 session 在旧令牌过期后刷新其 ID 令牌。
  • An ID token is force refreshed by calling currentUser.getIdToken(true).通过调用 currentUser.getIdToken(true) 强制刷新 ID 令牌。

So, if you need the client to immediately start using new claims, you should force a refresh using the third bullet point.因此,如果您需要客户立即开始使用新的声明,您应该使用第三个要点强制刷新。 Pass true to getIdToken.true传递给 getIdToken。

Ultimately, the answer is to not use custom tokens merely to add custom claims for your firebase rules.最终,答案是不要仅仅使用自定义令牌来为您的 firebase 规则添加自定义声明。 They are completely different concepts.它们是完全不同的概念。

Custom tokens are to implement an unsupported auth provider in addition to those Fb supports - ie Google, Microsoft, etc. Custom claims are key/val pairs you can leverage in your security rules and via the claims property on the user.getIdTokenResult() object in the client.除了那些 Fb 支持之外,自定义令牌还用于实现不受支持的身份验证提供程序 - 即 Google、Microsoft 等。自定义声明是您可以在安全规则中以及通过 user.getIdTokenResult() object 上的声明属性利用的键/值对在客户端。

The timeout issue I was debugging was due to trying to re-use the custom token, which doesn't need to be refreshed because it's not what is is for.我正在调试的超时问题是由于尝试重新使用自定义令牌,它不需要刷新,因为它不是目的。 getIdToken() returns the Id token encoded with any claims that were on the original custom token when it was minted. getIdToken() 返回使用原始自定义令牌铸造时的任何声明编码的 Id 令牌。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM