簡體   English   中英

為什么帶有“ immediate:false”的gapi.auth.authorize不關閉彈出窗口並觸發回調?

[英]Why gapi.auth.authorize with “immediate: false” doesn't close popup and fire callback?

我正在開發一些擴展名。 Google開發人員控制台已配置完畢,並且最終可以使用gapi進行工作,但是,例如UX,我遇到了問題。

所以這是我要實現的方案:

  1. 嘗試使用Google Chrome登錄用戶進行身份驗證。
  2. 如果失敗,請嘗試通過gapi.auth.authorize進行即時身份驗證:true。
  3. 如果失敗,請嘗試通過gapi.auth.authorize進行即時身份驗證:false。

而這種作品。 我得到要求許可的彈出窗口,單擊“接受”,但是彈出窗口變為空白,標題設置為“ Connecting ...”(未關閉),並且永遠不會觸發回調函數。

我知道訪問是被授予的,因為當我單擊接受並重新加載頁面時,它可以使用Instant:true進行授權,並且我的擴展程序可以正常工作。

我在Google搜索了幾個問題,主題和問題並詢問了不同的查詢以尋找答案,然后發現了以下解決方案:

  1. setTimeout(checkAuth,1)-嘗試過,沒有成功。
  2. 我推論不能在即時:真之后立即調用即時:假,因此我嘗試一下,嘗試首先使用即時:假進行身份驗證。 結果相同。
  3. 我嘗試添加gapi.auth.init,並在其回調中檢查Author(也使用setTimeout)。

因此,這里是一些代碼(background.js)。 抱歉,看起來像意大利面條,我是JS的初學者。

function respond(interactive, sendResponse) {
    xhrWithAuth('GET',
        'https://www.googleapis.com/gmail/v1/users/me/profile',
        interactive, // false
        onUserMailFetched, sendResponse);

    function xhrWithAuth(method, url, interactive, callback, sendResponse) {
        var access_token;
        var retry = true;

        getToken();
        // 1. trying to use Chrome user
        function getToken() {
            chrome.identity.getAuthToken({
                interactive: interactive
            }, function (token) {
                if (chrome.runtime.lastError) {
                // 2. here lastError is User is not signed in. Calling onUserMailFetched
                    callback(chrome.runtime.lastError, null, null, sendResponse);
                }
                access_token = token;
                requestStart();
            });
        }
        // I guess not important in topic
        function requestStart() {
            var xhr = new XMLHttpRequest();
            xhr.open(method, url);
            xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
            xhr.onload = requestComplete;
            xhr.send();
        }
        // I guess not important in topic
        function requestComplete() {
            if (this.status == 401 && retry) {
                retry = false;
                chrome.identity.removeCachedAuthToken({
                        token: access_token
                    },
                    checkAuth_neverCalled);
            } else {
                callback(null, this.status, this.response, sendResponse);
            }
        }
        // I guess not important in topic
        function checkAuth_neverCalled() {
            console.log("checking auth when getAuthToken fails");
            gapi.auth.authorize({
                client_id: OAUTH2_CLIENT_ID,
                scope: OAUTH2_SCOPES,
                immediate: false
            }, handleAuthResult);

            // Handle the result of a gapi.auth.authorize() call.
            function handleAuthResult(authResult) {
                console.log("authenticated: ", authResult);
                if (authResult) {
                    // do something with data
                } else {
                    consoel.log("failed");
                }
            }
        }
    }

    // This is important part.
    function onUserMailFetched(error, status, response, sendResponse) {
        if (!error && status == 200) {
            // do something with data
        } else {
         // 3. as we have error at first call, we checkAuth with immediate = true
            setTimeout(function () {
                checkAuthWhenNotLogged(sendResponse, true);
            }, 10);
        }
    }
    // This is important part.
    function checkAuthWhenNotLogged(sendResponse, immediateVal) {
        gapi.auth.authorize({
            client_id: OAUTH2_CLIENT_ID,
            scope: OAUTH2_SCOPES,
            immediate: immediateVal
        }, handleAuthResult);

        // Handle the result of a gapi.auth.authorize() call.
        // 5. But this function is never called again (when called with false).
        function handleAuthResult(authResult) {
            if (authResult) {
            // 4. and this is called when checkAuth with true fail. We call checkAuth (itself) with false.
                if (authResult.error == "immediate_failed") {
                    gapi.auth.init(function () {
                        setTimeout(function () {
                            checkAuthWhenNotLogged(sendResponse, false);
                        }, 10);
                    });
                } else {
                // yay, we are authneticated and can call gmail service
                    gapi.client.load('gmail', 'v1', function () {
                        var request = gapi.client.gmail.users.getProfile({
                            'userId': 'me'
                        });
                        request.execute(function (profile) {
                            // do something with data
                        });
                    });
                }
            } else {
                console.log("failed");
            }
        }
    }
}

任何提示,鏈接或解決方案都將受到重視。

好的,這是使OAuth2正常工作的方法。

場景如下:

  1. 嘗試使用Google Chrome登錄用戶進行身份驗證。
  2. 如果失敗,請嘗試通過gapi.auth.authorize進行即時身份驗證:true。
  3. 如果失敗,請嘗試使用chrome.identity.launchWebAuthFlow

首先,我需要解釋為什么launchWebAuthFlow不能更早地工作。 如前所述,我配置了Google Developers Console,並為Chrome應用程序創建了密鑰和客戶端ID。 這對於launchWebAuthFlow是錯誤的。 它應該是具有配置的重定向URL的Web應用程序。

在chrome擴展程序中,這是獲取重定向URL的方法:var redirectURL = chrome.identity.getRedirectURL(“ suffix”); 它將創建如下內容:https:// {appId} .chromiumapp.org /

您需要在客戶端ID配置中將此設置為重定向鏈接。 就我而言,我必須在js代碼中更改已使用的客戶端ID。

這是對我有用的代碼:

(...)
var redirectURL = chrome.identity.getRedirectURL();
var options = {
    'interactive': true,
    url: 'https://accounts.google.com/o/oauth2/auth?' +
        'scope=profile email' +
        '&response_type=token' +
        '&client_id=' + OAUTH2_CLIENT_ID_WEB +
        '&redirect_uri=' + redirectURL
}
chrome.identity.launchWebAuthFlow(options, function (redirectUri1) {
    if (chrome.runtime.lastError) {
        console.log(chrome.runtime.lastError);
    } else {
        // redirectUri is a link with access_token param inside, we need to extract it
        var paramName = "access_token"
        var results = new RegExp(paramName + '=([^&#]*)').exec(redirectUri1);
        if (results == null) {
            console.log("not found");
        } else {
            console.log(results[1] || 0);
            access_token = results[1]; // here we set the token
            requestStart(); // here I launch google api request
        }
    };
});
(...)
function requestStart() {
        // url = 'https://www.googleapis.com/plus/v1/people/me'
        // method = 'GET'
        var xhr = new XMLHttpRequest();
        xhr.open(method, url);
        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
        xhr.onload = requestComplete;
        xhr.send();
    }

function requestComplete() {
    if (this.status == 401 && retry) {
        retry = false;
        chrome.identity.removeCachedAuthToken({
                token: access_token
            },
            checkAuth);
    } else {
        callback(this.status, this.response);
    }
}

希望有人會利用這一點。 我知道我花了太多時間在此上。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM