Facebook OAuth登录 - access_token API返回“此授权代码已被使用”

时间:2013-09-27 10:00:34

标签: facebook oauth facebook-login facebook-oauth facebook-authentication

这个问题已在Stack上被问过几次,但是没有真正的答案。让我试着解释一下我的情况。

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

申请流程

第1步:用户在我们的网站上按下Facebook登录按钮

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

第3步:在授权应用程序时,回调会进入我们的应用程序,并带有一个短暂的“代码”参数。

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

第4步中的错误:

当我们尝试为访问令牌交换短生活“代码”时,我们从Facebook收到此错误。

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

观察:

  1. 对于新来的用户,不会发生上述错误。
  2. 对于返回的用户,此调用因上述错误而失败。
  3. 我们的应用程序现已运行超过9个月,此错误仅在过去7-10天内出现。在此之前,我们已有成千上万的用户成功使用它。
  4. 我从论坛获得的内容:

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

    真正困扰我的是什么?

    1. 建议的解决方案假定他们创建的cookie始终存在于用户的浏览器中。这是一个不好的假设,因为cookie可能随时被删除。
    2. 我有另一个应用程序ID / app秘密,我用于我的开发(即localhost),并且完美无缺。登录在那里很好,但它只是有问题的产品机器。
    3. 自从我们推出应用程序以来,这个问题在生产机器上发生了近10个月,而且它突然发生了。最糟糕的是,我无法得到任何破坏这种流动的最近变化的记录。
    4. 修改

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

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

2 个答案:

答案 0 :(得分:4)

我通过使用随机GUID解决了这个问题,该GUID附加到我传入facebook的每个回调网址。看来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交换该代码时:

var facebook = new FacebookClient();

dynamic result = facebook.Post("oauth/access_token", new
{
    client_id = ...,
    client_secret = ...,
    redirect_uri = ..."/facebook/oauthcallback?buster=" + Session["facebook_buster"].ToString(),
    code = Request["code"] // this is the returned code from the first method
});

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

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

希望这有帮助!

答案 1 :(得分:0)

我今天也在努力解决这个问题。不确定你是否正在使用Facebook PHP类(从你写的东西,似乎你没有),但是,它可能是一个指针 - 问题是Facebook PHP库似乎从代码中获取令牌自动,我试图再次这样做。