我正在开发一些扩展名。 Google开发人员控制台已配置完毕,并且最终可以使用gapi进行工作,但是,例如UX,我遇到了问题。

所以这是我要实现的方案:


尝试使用登录的Google Chrome进行身份验证。
如果失败,请尝试通过gapi.auth.authorize进行即时身份验证:true。
如果失败,请尝试通过gapi.auth.authorize进行即时身份验证:false。


而这种作品。我得到要求许可的弹出窗口,单击“接受”,但是弹出窗口变为空白,标题设置为“ Connecting ...”(未关闭),并且永远不会触发回调函数。

我知道访问是被授予的,因为当我单击接受并重新加载页面时,它可以使用Instant:true进行授权,并且我的扩展程序可以正常工作。

我在Google搜索了几个问题,主题和问题并询问了不同的查询以寻找答案,然后发现了以下解决方案:


setTimeout(checkAuth,1)-尝试过,没有成功。
我推论不能在即时:真之后立即调用即时:假,因此我尝试一下,并尝试首先使用即时:假进行身份验证。结果相同。
我尝试添加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正常工作的方法。

场景如下:


尝试使用Google Chrome登录用户进行身份验证。
如果失败,请尝试通过gapi.auth.authorize进行即时身份验证:true。
如果失败,请尝试使用chrome.identity.launchWebAuthFlow


首先,我需要解释为什么launchWebAuthFlow不能更早地工作。如前所述,我配置了Google Developers Console,并为Chrome应用程序创建了密钥和客户端ID。这对于launchWebAuthFlow是错误的。它应该是具有配置的重定向URL的Web应用程序。

在chrome扩展程序中,这是如何获取重定向网址的方法:
    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);
    }
}


希望有人会利用这一点。我知道我花了太多时间在此上。

10-07 21:42