15

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

我们使用一个使用 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 天代码到期。所以我们应该在用户的浏览器上创建一个带有访问令牌的 cookie。我什至可以看到人们修改他们的代码以创建 cookie。

真正困扰我的是什么?

  1. 建议的解决方案假定他们创建的 cookie 将始终存在于用户的浏览器中。这是一个不好的假设,因为 cookie 可能随时被删除。
  2. 我有另一个用于我的开发的应用程序 ID/应用程序密码(即本地主机),并且效果很好。登录在那里很好,但只有产品机器有问题。
  3. 自从我们推出应用以来,生产机器上已经有近10个月没有出现这个问题了,它突然出现了。最糟糕的是,我无法获得任何打破这一流程的最近更改的记录。

编辑:

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

希望这里有足够的信息表明我们的代码并非完全不正确。欢迎遇到并解决此问题的人提供的任何提示/指针。如果它是 Facebook 的错误,并且 Facebook 开发人员注意到了,我会更开心。

4

2 回答 2

4

我通过使用随机 GUID 解决了这个问题,该 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 时:

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 进行测试,并且每次都有效。

希望这可以帮助!

于 2013-09-29T12:03:04.883 回答
0

我今天也为此挣扎了一段时间。不确定您是否正在使用 Facebook PHP 类(从您编写的内容来看,您似乎没有使用),但是,无论如何它可能是一个指针 - 问题是 Facebook PHP 库似乎从代码中获取了令牌自动,我试图再做一次。

于 2013-09-27T13:47:45.897 回答