错误:Firebase ID 令牌已过期

Posted

技术标签:

【中文标题】错误:Firebase ID 令牌已过期【英文标题】:Error: Firebase ID token has expired 【发布时间】:2018-05-27 23:03:52 【问题描述】:

在我的服务器上,我在使用 firebase admin sdk .verifyIdToken() 时看到了这些错误

Firebase ID 令牌已过期。从您的客户端应用获取新令牌并重试

Firebase ID 令牌具有与已知公钥不对应的“孩子”声明。 ID 令牌很可能已过期,因此请从您的客户端应用程序获取新令牌并重试。有关如何检索 ID 令牌的详细信息,请参阅 https://firebase.google.com/docs/auth/admin/verify-id-tokens。

在客户端,我在浏览器 服务器之间的每个请求之前执行此操作:

firebase.auth().currentUser.getIdToken()

通过阅读文档,我了解到此函数将获得一个有效的、未过期的令牌,因为后台的 SDK 会根据需要自行刷新。或者,我可以将true 传递给此函数以强制刷新。

为什么这个getIdToken() 函数似乎正在向我的后端发送过期的令牌?

似乎可以解决这个问题,我的选择是:

    每次调用 getIdToken() 时传入 true 以强制刷新。这是不必要的昂贵,因为它会在来自浏览器 我的服务器的请求之前添加来自浏览器 firebase 的整个往返网络请求的开销 以我现在的方式调用getIdToken() - 在客户端手动解码令牌,检查过期时间,如果过期则再次调用getIdToken(true) 强制刷新并将新刷新的令牌发送到我的服务器

2 号是推荐/预期的处理方式吗?这里好像有什么问题……

【问题讨论】:

您找到解决方案了吗?我看到了类似的症状。 @puelo 一样,你能解决它吗? @MartinDeSimone 不。它似乎并不经常发生,所以我没有再看一眼。这可能是由一些时间差异引起的。可能(没有来自 firebase 的任何代码)检查过期没有提供任何缓冲区,因此在某些情况下可能处于边缘。 Firebase 将令牌存储在 cookie 中,因此大约一个小时后,令牌就会过期。此时,用户向服务器提交请求(不知道他们有过期的令牌)。服务器读取令牌并尝试验证它,但验证返回“过期”。因此,正如答案所建议的,您需要在每次提交请求之前验证令牌。我不确定为什么 Firebase 文档没有提到这一点。这似乎是一个糟糕的设计。刷新页面将强制客户端上的 javascript 中的 firebase api 再次获取新令牌。 【参考方案1】:

令牌通常会在一个小时后过期。 getIdToken 将刷新缓存的令牌,如果它过期。当您需要将令牌发送到服务器时,请确保始终在客户端调用它。如果您缓存令牌并始终将其发送到您的后端,它将在某个时候过期。

为了以防万一,请确保您的服务器时钟同步。这不太可能,但您的时钟可能由于某种原因不同步。

【讨论】:

"> verifyIdToken 将刷新缓存的令牌,如果它过期了" 服务器时钟已同步,此服务器在heroku上,似乎不是时钟同步问题 对不起,我的意思是getIdToken。我道歉。已经是深夜了 :) 我修正了错字。每当您需要向服务器发送经过身份验证的请求时,您都需要调用它。 但这里的问题是,这是 firebase 的好设计吗?拥有一个每小时过期的令牌,并且必须在将其发送到后端服务器之前刷新,这似乎是 IMO 一个糟糕的设计。我已经看到 getIdToken() 调用最多需要 10 秒才能返回,因此让用户等待 10 秒是非常糟糕的用户体验。我觉得我必须在这里遗漏一些东西? 您从哪里得知刷新需要 10 秒?这没有任何事实依据。使用短命代币可以最大限度地减少攻击窗口,并且是一个成熟的行业标准。【参考方案2】:

尝试使用更像这样的东西:

Auth.auth().currentUser.getIDTokenForcingRefresh(true)  (token, err) in

/* your code to manage error and success */


【讨论】:

【参考方案3】:

您是否注意到有一种异步方式来获取令牌?

            mAuth.getCurrentUser().getIdToken(false).addOnSuccessListener(new OnSuccessListener<GetTokenResult>() 
            @Override
            public void onSuccess(GetTokenResult getTokenResult) 
                long time = System.currentTimeMillis() - starttime;

                Log.d("testt", "time " + time + ", token " + getTokenResult.getToken());
            
        );

不确定,但我猜它会进行内部检查,如果令牌不再有效(例如,当前用户有一个刷新的令牌广播,但由于某种原因它没有到达用户,网络问题例如),它请求新的并返回。

附:我也在对这个主题进行研究,如果发现任何新内容,我会更新。

【讨论】:

【参考方案4】:

上面提到的另一个可能的解决方案是您的浏览器(或系统)日期错误。它几乎总是与日期有关吗?

【讨论】:

浏览器或系统时间与令牌过期有何关系?您没有在本地验证令牌,它在 Firebase 上得到验证。因此,当您获得令牌时,您会从 frebase 获得令牌到期时间,当您验证令牌时,您将在 firebase 上对其进行验证,以便 firebase 在发出令牌的同一机器上检查 exp 时间......据我所知,当地时间不应该有对它的任何影响。如果是这样,那么如果 Firebase 服务器位于 +1 时区,您在 +4h 时区发出的令牌将立即过期。还是? 不认识老兄。我不记得偏移量是多少(我认为大约是一天),但是由于系统日期错误,它不起作用,一旦我更改它,它就起作用了。你可以从投票中看到它也帮助了其他人。 简直不敢相信 :) 如果您自己在一台服务器上发行令牌并在另一台服务器上验证它们,时间偏移会影响令牌。否则 - 如果根据已发布它并在同一服务器上检查的服务器上的时间设置令牌中的 exp 时间。 你说的很有道理。但是这个答案有时仍然可以解决问题,如果您有时间自己测试一下,如果系统日期错误,它将无法正常工作,我不知道是令牌还是什么。有时你不需要所有的答案。【参考方案5】:

如果您在后端使用令牌,则可以执行以下操作,

1.后端检查token

2.如果token过期,发送401未授权。

3.在客户端,检查状态码是否为未经授权的401,如果是则调用getIdToken并保存新令牌

【讨论】:

【参考方案6】:

我在尝试和错误之前和之后都遇到过同样的问题,我发现这是由时间同步引起的。

我将计算机时间和时区设置为自动并修复了该问题。 另外,记得在getIdToken(true)中加上“true”

【讨论】:

添加真正的方法,代替您的令牌 @MaduekweChukwuemeka 在这里你可以放置更改 getIdTokenResult(forceRefresh?: boolean)【参考方案7】:
Error: Firebase ID token has expired

当您的设备时间错误时,您会收到此错误消息。还要检查您的设备时钟时间。

【讨论】:

以上是关于错误:Firebase ID 令牌已过期的主要内容,如果未能解决你的问题,请参考以下文章

Firebase Android 身份验证失败:expired_token(身份验证令牌已过期)

加载操作中的 BigQuery 错误:令牌无效 - 令牌无效:无状态令牌已过期

Firebase Auth ID 令牌的“aud”声明不正确

CloudKit 错误:更改令牌已过期,需要重置

facebook 访问令牌已过期

Firebase 令牌在 1 小时内过期后如何保留用户?