这个问题已在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}}
观察:
我从论坛获得的内容:
以下是我对所读内容的解释。可能不准确。 Facebook有一些奇怪的政策,需要应用程序开发人员维护临时的10分钟代码,直到第一次登录期间获得的60天代码到期为止。因此,我们应该在用户的浏览器上创建一个带有Access令牌的cookie。我甚至能够看到人们修改他们的代码以创建cookie。
真正困扰我的是什么?
修改
平台: Python,Google Appengine。我们不使用任何Facebook SDK,我们对所有登录URL进行直接HTTP调用。 呼叫失败:https://graph.facebook.com/oauth/access_token - 我们在第一次呼叫发生后的20秒内传递appId,密码和代码(从facebook获取)。
希望这里有足够的信息来证明我们的代码并非完全错误。来自遇到并解决此问题的人的任何提示/指示都是欢迎。如果它是Facebook的错误,Facebook开发者会注意到,我会更高兴。
答案 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库似乎从代码中获取令牌自动,我试图再次这样做。