[英]Why gapi.auth.authorize with “immediate: false” doesn't close popup and fire callback?
I'm working on some chrome-extension. 我正在开发一些扩展名。 The Google Developer Console is configured and using gapi eventually works, but I've got problem with, let's say, UX.
Google开发人员控制台已配置完毕,并且最终可以使用gapi进行工作,但是,例如UX,我遇到了问题。
So here is scenario I'm trying to acheive: 所以这是我要实现的方案:
And this kind of works. 而这种作品。 I get the popup which asks for permission, I click Accept, but then popus goes blank, title is set to "Connecting..." (doesn't close) and callback function is never fired.
我得到要求许可的弹出窗口,单击“接受”,但是弹出窗口变为空白,标题设置为“ Connecting ...”(未关闭),并且永远不会触发回调函数。
I know access is granted because when I click accept and reload the page, it can authorize using immediate:true and my extension works perfectly. 我知道访问是被授予的,因为当我单击接受并重新加载页面时,它可以使用Instant:true进行授权,并且我的扩展程序可以正常工作。
I check few issues, topics and questions asking different queries in google searching for the answer and I found this sollutions: 我在Google搜索了几个问题,主题和问题并询问了不同的查询以寻找答案,然后发现了以下解决方案:
So here is bit of code (background.js). 因此,这里是一些代码(background.js)。 Sorry it looks like spaghetti, I'm beginner in 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");
}
}
}
}
Any hint, link or solution will be apreciated. 任何提示,链接或解决方案都将受到重视。
Ok, here is what I did to make OAuth2 work. 好的,这是使OAuth2正常工作的方法。
Scenario looks like: 场景如下:
First of all I need to explain why launchWebAuthFlow wasn't working earlier. 首先,我需要解释为什么launchWebAuthFlow不能更早地工作。 As I mention, I configured the Google Developers Console and created key and client id as for Chrome Application.
如前所述,我配置了Google Developers Console,并为Chrome应用程序创建了密钥和客户端ID。 This was wrong for launchWebAuthFlow.
这对于launchWebAuthFlow是错误的。 It should be Web Application with configured redirect URL.
它应该是具有配置的重定向URL的Web应用程序。
In chrome extension here is how you can get redirect url: var redirectURL = chrome.identity.getRedirectURL("suffix"); 在chrome扩展程序中,这是获取重定向URL的方法:var redirectURL = chrome.identity.getRedirectURL(“ suffix”); It will create something like this: https://{appId}.chromiumapp.org/
它将创建如下内容:https:// {appId} .chromiumapp.org /
You need to set this as redirect link in your Client ID configuration. 您需要在客户端ID配置中将此设置为重定向链接。 In my case I had to change used Client ID in js code.
就我而言,我必须在js代码中更改已使用的客户端ID。
Here is code that works for me: 这是对我有用的代码:
(...)
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);
}
}
Hope someone will take advantage of this. 希望有人会利用这一点。 I know I spent way too much time on this.
我知道我花了太多时间在此上。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.