错误:Firebase ID令牌已过期

错误:Firebase ID令牌已过期,firebase,firebase-authentication,Firebase,Firebase Authentication,在我的服务器上,当使用firebase admin sdk时,我看到了这些错误。verifyIdToken() Firebase ID令牌已过期。从客户端应用获取新令牌,然后重试 Firebase ID令牌具有与已知公钥不对应的“kid”声明。ID令牌很可能已过期,因此请从客户端应用程序获取新令牌,然后重试。有关如何检索ID令牌的详细信息,请参阅 在客户端,我会在浏览器和服务器之间的每个请求之前执行此操作: 通过阅读文档,我了解到该函数将获得一个有效的、未过期的令牌,因为后台的SDK将根据需要刷

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

Firebase ID令牌已过期。从客户端应用获取新令牌,然后重试

Firebase ID令牌具有与已知公钥不对应的“kid”声明。ID令牌很可能已过期,因此请从客户端应用程序获取新令牌,然后重试。有关如何检索ID令牌的详细信息,请参阅

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

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

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

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

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

  • 2号是处理这一问题的推荐/预期方法吗?这里似乎出了问题……

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


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

    请尝试使用类似的方法:

    Auth.auth().currentUser.getIDTokenForcingRefresh(true) { (token, err) in
    
    /* your code to manage error and success */
    
    }
    

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

                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());
                }
            });
    
    mAuth.getCurrentUser().getIdToken(false).addOnSuccessListener(新的OnSuccessListener()){
    @凌驾
    成功时公共无效(GetTokenResult GetTokenResult){
    长时间=System.currentTimeMillis()-starttime;
    Log.d(“testt”,“time”+time+,token“+getTokenResult.getToken());
    }
    });
    
    不确定,但我猜它会进行内部检查,如果令牌不再有效(例如,当前用户有一个刷新的令牌广播,但由于某种原因它没有到达用户,例如网络问题),它会请求新的令牌并返回该令牌


    另外,我也在研究这个话题,如果有新的发现,我会及时更新。

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

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

    1.检查后端上的令牌

    2.如果令牌已过期,则发送401未经授权


    3.在客户端上,检查状态代码是否为401 Unauthorized,如果是,请调用
    getIdToken
    并保存新的token

    在尝试和出错之前和之后,我遇到了相同的问题,我发现这是由时间同步引起的

    我将我的电脑时间和时区设置为自动,并解决了这个问题。 另外,记住在getIdToken中添加“true”(true)


    当您的设备时间错误时,您将收到此错误。同时检查您的设备时钟时间。

    “>
    verifyIdToken
    将在缓存令牌过期时刷新该令牌”<这是否意味着在发送之前需要在客户端调用verifyIdToken?我在文件里没看到。。。我想你的意思是说getIdToken()将刷新。。。我每次在发送请求之前都会打这个电话。我将检查服务器时钟服务器时钟是否同步,此服务器在heroku上,似乎不是时钟同步问题。我是说
    getIdToken
    。我道歉。那是深夜:)我修正了打字错误。每当您需要向服务器发送经过身份验证的请求时,都需要调用它。但这里的问题是,firebase的设计好吗?拥有一个每小时过期一次并且在发送到后端服务器之前必须刷新的令牌,在我看来是一个糟糕的设计。我已经看到getIdToken()调用最多需要10秒才能返回,因此让用户等待10秒是一种非常糟糕的用户体验。我觉得我一定是错过了什么?你从哪里知道刷新需要10秒?这没有事实依据。使用短期代币可以最大限度地减少攻击窗口,这是一个公认的行业标准。您有没有找到解决方案?我看到了类似的症状。@puelo Same,你能治好吗?@MartinDeSimone不。这似乎并不经常发生,所以我没有再看一眼。这可能是由于时差造成的。可能是(没有来自firebase的任何代码)过期检查没有提供任何缓冲区,因此在某些情况下可能处于边缘。firebase将令牌存储在cookie中,因此大约一小时后,令牌将过期。此时,用户向服务器提交请求(不知道他们有过期的令牌)。服务器读取令牌并尝试对其进行验证,但验证返回“expired”。因此,正如答案所建议的,您需要在每次提交请求之前验证令牌。我不知道为什么Firebase文档没有提到这一点。这看起来确实是个糟糕的设计。刷新页面将强制客户端上javascript格式的firebase api再次获取新令牌。浏览器或系统时间与令牌过期有何关系?您不是在本地验证令牌,而是在Firebase上进行验证。所以当你得到代币时,你就得到了代币到期日
                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());
                }
            });
    
    Error: Firebase ID token has expired