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

相關問題