14

这个问题已被问了几次堆栈,但一直没有真正的答案。无论如何,让我试着解释我的情况。Facebook OAuth登录 - 访问_token API返回“此授权码已被使用”

我们使用使用Facebook OAuth2登录的应用程序。这个登录过去一直工作良好,直到上周,突然间它现在让我们感到困扰。

申请流程:

步骤1:用户按下与Facebook按钮,登录我们的网站上

第2步:重定向到Facebook的登录/授权页面

第3步:在授权应用程序时,回调来到我们的应用程序,使用短暂的“代码”参数。

第4步:使用“https://graph.facebook.com/oauth/access_token”URL将此“代码”参数交换为60天的访问令牌。

错误步骤4:

当我们试图交流简短生活“代码”的访问令牌,我们得到了来自Facebook这个错误。

{"error":{"message":"This authorization code has been used.","type":"OAuthException","code":100}} 

观察:

  1. 对于用户谁是新来到应用程序,不会出现上面所说的错误。
  2. 对于返回的用户,此调用失败,出现上述错误。
  3. 我们的应用程序现在已经运行了9个多月,而且这个错误在过去的7-10天内才出现。我们有成千上万的用户在此之前成功使用它。

我已经从论坛获得:

这里是我的什么我读的解释。可能不准确。 Facebook有一些奇怪的政策,需要应用程序开发人员维护临时10分钟的代码,直到在第一次登录期间获得的60天代码过期。所以我们应该在用户浏览器上用Access令牌创建一个cookie。我甚至能够看到人们修改他们的代码以创建cookie。

什么让我感到困扰?

  1. 建议的解决方案假定他们创建的cookie始终存在于用户的浏览器中。这是一个糟糕的假设,因为Cookie可能随时被删除。
  2. 我有另一个应用程序Id /应用程序的秘密,我用于我的发展(即本地主机),并完美的作品。登录发生在那里,但它唯一的问题产品机器。
  3. 自从我们推出这款应用程序以来,近10个月的时间里,这个问题并没有在生产机器上发生,而且它突然之间出现了。最糟糕的是,我无法获得任何破坏此流程的最新变化记录。

编辑:

平台: Python中,谷歌的AppEngine。我们不使用任何Facebook SDK,我们直接对所有登录URL进行HTTP调用。 调用失败:https://graph.facebook.com/oauth/access_token - 我们在第一次调用发生后的20秒内传递appId,秘密和代码(从facebook获得)。

希望这里有足够的信息来表明我们的代码并不完全错误。来自遇到并解决此问题的人的任何提示/指示是欢迎。如果它的Facebook bug和Facebook开发者注意到了,我会更加快乐。

+0

代码参数只能为用户访问令牌交换一次。您的问题缺少有关您使用的平台/语言以及您的确切API调用的可用信息。 – CBroe

+0

@CBroe - 感谢您的通知。是的 - 我们明白代码参数是一次性的,这就是为什么我们想要将它交换为access_token,但访问令牌URL失败。我已经包含了有关平台/语言的信息。 – Srivatsan

回答

0

我今天也为此苦苦挣扎了一段时间。不知道你是否使用Facebook PHP类(从你写的,看起来你没有),然而,它可能是一个指针反正 - 问题是Facebook的PHP库似乎从代码中获取令牌自动和我试图再次做。

+0

我也有这个问题。在我使用Facebook PHP SDK之前,当我调用上面的第4步(graph.facebook.com/oauth/access_token)时,它工作正常。但是如果我在之后调用它,我会得到“此授权码已被使用”。存储在SDK中的令牌与端点返回的令牌格式不同,我没有在SDK中看到过期日期。所以,如果这些令牌不同,为什么Facebook在这种情况下返回错误? –

4

我通过使用一个随机的GUID绕过这个问题,它附加到我传递到Facebook的每个回调URL。看起来Facebook返回的代码由几个部分组成,包括您必须指定的redirect_uri参数。通过使用这种GUID技巧,你的应用程序继续工作,但Facebook认为它是一个不同的URL,因此生成一个新的代码。

如果将该GUID存储在临时会话中,它总是相同的。这是我的意思是一个非常简化的版本。我使用C#,但该解决方案将是相同的:

之前,我开始了OAuth的过程:

Session["facebook_buster"] = System.Guid.NewGuid().ToString(); 

然后揭开序幕登录:

var facebook = new FacebookClient(); 

var loginUrl = facebook.GetLoginUrl(new 
{ 
    client_id = ..., 
    redirect_uri = ..."/facebook/oauthcallback?buster=" + Session["facebook_buster"].ToString(), 
    display = "popup", 
    scope = "publish_stream,user_photos" 
}); 

然后在我的回调方法,当我想交换代码为一个新的access_token:

注意在第二种方法我是usi使用相同的会话密钥,以便授权代码成功。

一整个早上通过撤销权限/手动更改存储的access_token(在我的数据库)/完全删除我存储的access_token并且每次都有效。

希望这会有所帮助!

+1

没有雪茄,https://github.com/HabitRPG/habitrpg/issues/4221#issuecomment-61855507 – lefnire

+0

谢谢先生。乍一看,我想这不应该工作。但我用PHP实现它,瞧!再次长期访问令牌。 对于这个问题的新手,Facebook必须在生成长期代码时使用您的'redirect_uri'参数。本质上,我们正在欺骗他们的算法,在没有10分钟时间的情况下制作独特的长期代码。绝对天才。 –

+0

只是一个FYI,添加一个缓存断路器参数给我的redirect_uri,当在PHP中获取登录网址时,它得到了与此相同的结果,我假设它工作.. :)不能相信这个错误与FB。有点可笑吗?它说我已经使用认证码,如果我保持redirect_uri与之前的认证尝试相同?真的很困惑,哦。 – jfaron

相关问题