2016-02-29 71 views
1

我一直在研究這個問題很長一段時間,並沒有成功。希望有人能夠對此有所瞭解!chrome.identity.launchwebauthflow特定用戶失敗

我正在使用谷歌瀏覽器擴展程序(瀏覽器操作),在Google之外進行身份驗證/授權(chrome.identity.launchwebauthflowinteractive設置爲true)。我們對某些用戶的認證/授權流程取得了成功,但並非全部。下面是有趣的結果:

  1. 用戶A點擊擴展圖標,點擊授權按鈕,成功獲取授權碼,交換訪問令牌,並可繼續使用該應用程序。
  2. 用戶B點擊擴展圖標,點擊授權按鈕,擴展彈出窗口關閉。它在交換代碼訪問令牌之前失敗。
  3. 用戶B右擊擴展圖標,選擇Inspect彈出窗口,點擊授權按鈕,成功獲取認證碼,交換訪問令牌,並可繼續使用該應用程序。
  4. 用戶A使用網絡以安全模式啓動設備。用戶A點擊擴展圖標,點擊授權按鈕,擴展彈出窗口關閉。它在交換代碼訪問令牌之前失敗。
  5. 用戶A使用網絡以安全模式啓動設備。用戶A打開一個標籤並加載該分機的網址(chrome-extension://pathofextension)。用戶單擊授權按鈕,成功獲取授權碼,將其交換爲訪問令牌,並可繼續使用該應用程序。
  6. 擴展轉換爲打包的應用程序。用戶A和B打開應用程序,單擊授權按鈕,成功獲取授權碼,將其交換爲訪問令牌,然後繼續使用該應用程序。

我們認爲這是一個客戶端問題,但我們都使用相同的Chrome版本。什麼會導致擴展程序的彈出窗口在驗證碼返回時關閉?我們無法保持開發者控制檯處於打開狀態,以查看是否出現任何錯誤,因爲開發者控制檯處於打開狀態時工作得很好。我們使用$.ajaxSetup({ cache:false })來確保緩存對於Ajax請求是禁用的。

這裏的chrome.identity.launchwebauthflow調用(最初是從彈出的稱呼)的一個片段:

chrome.identity.launchWebAuthFlow({url:url,interactive:true},function(response) { 
    console.log('OAuth Response: '+response); 
    if (response) { 
     var authCode = encodeURIComponent(response.substring(response.indexOf('=')+1)); 
     console.log('Auth Code: '+authCode); 
     userAuthorization(authCode); 
    } else { 
     authorizeButton(); 
    } 
}); 

編輯的代碼嘗試應用的代碼,在背景的解決方案後:

彈出腳本現在調用後臺腳本:

chrome.runtime.sendMessage({type:'authorize',url:url},function(response) { 
    console.log(chrome.runtime.lastError); 
    console.log(response); 
    if (response && response.authCode) { 
     userAuthorization(response.authCode); 
    } else { 
     authorizeButton(); 
    } 
}); 

後臺腳本r支持彈出腳本。

chrome.runtime.onMessage.addListener(function(message,sender,sendResponse) { 

    if (message.type == 'authorize') { 

     var url = message.url, 
      authCode; 

    chrome.identity.launchWebAuthFlow({url:url,interactive:true},function(response) { 
      console.log('OAuth Response: '+response); 
      if (response) { 
       authCode = encodeURIComponent(response.substring(response.indexOf('=')+1)); 
       console.log('Auth Code: '+authCode); 
      } 
      sendResponse({authCode:authCode}); 
     }); 

    } 

    return true; 

}); 
+0

'launchWebAuthFlow'從哪裏調用?彈出代碼? – Xan

+0

launchwebauthflow是從彈出窗口的JavaScript內部調用的(當您單擊該擴展的圖標並彈出窗口出現時)。 – jacorre

回答

0

從擴展彈出框調用launchWebAuthFlow是一個非常糟糕的主意。

此操作應該創建一個新窗口並關注它。通過Chrome用戶界面慣例,這應該關閉擴展彈出窗口 - 並使用它,徹底銷燬該頁面的JavaScript上下文。將不再有任何回調呼叫。

這解釋了爲什麼「Inspect popup」有助於 - 這可以防止關閉焦點丟失彈出窗口。在本調試案例之外的There is no override for this mechanism

此彈出式解僱行爲may subtly differ by OS,因此您可能沒有在您的開發計算機上看到它。但是約定很明確 - 任何焦點丟失都會破壞彈出頁面。

唯一的真正的持久你不能意外關閉的擴展的一部分是後臺腳本 - 這是你應該處理授權的地方。從彈出的代碼發送一條消息,請求它。

更新:請注意,由於相同的原因,您不能返回對sendMessage的響應 - 彈出窗口不再存在。您的邏輯應該是每次彈出窗口打開時嘗試使用interactive: false檢索令牌 - 如果失敗,請求後臺啓動交互式流程(並且期望關閉,因此不需要sendResponse)。

+0

用戶測試正在使用相同的操作系統,但我很欣賞從後臺腳本進行呼叫的反饋。我會試一試。謝謝! – jacorre

+0

它也可以是競爭條件 - 彈出關閉後JS上下文的銷燬速度有多快。 – Xan

+0

對於不適用的用戶,他們看到以下錯誤: 響應identity.launchWebAuthFlow時出錯:錯誤:試圖使用斷開連接的端口對象 聽起來像是計時事物嗎?我正在使用一個後臺腳本,其中launchwebauthflow被調用,我沒有定義持久標誌。 – jacorre