Reputation: 33
I've been researching this issue for quite some time now and have had no success. Hoping someone can shed some light on this!
I'm working on an Google Chrome Extension (browser action) where authentication/authorization is being done outside of Google (chrome.identity.launchwebauthflow
with interactive
set to true
). We've had success with the authentication/authorization flow for some users but not all. Here are the interesting results:
chrome-extension://pathofextension
). User clicks Authorize button, successfully gets auth code, exchanges it for access tokens, and can proceed with using the application.We think it's a client issue, but we're all using the same Chrome versions. What would cause the extension's pop up window to close when the auth code is being returned? We can't keep the developer console open to see if any errors appear because when the developer console is open it works just fine. We are using $.ajaxSetup({ cache:false })
to make sure caching is disabled for ajax requests.
Here's a snippet of the chrome.identity.launchwebauthflow call (originally called from the popup):
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();
}
});
Edited code after trying to apply the code-in-background solution:
Pop up script now calls background script:
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();
}
});
Background script responds to pop up script.
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;
});
Upvotes: 3
Views: 2122
Reputation: 77523
Invoking launchWebAuthFlow
from an extension popup is a very bad idea.
This operation is supposed to create a new window and focus on it. By Chrome UI conventions, this should close the extension popup - and with it, completely destroy the JavaScript context of that page. There will no longer be any callback to call.
This explains why "Inspect popup" helps - this prevents closing the popup on focus loss. There is no override for this mechanism outside of this debugging case.
This popup-dismissal behavior may subtly differ by OS, hence you might not have seen it on your development machine. But the convention is clear - any loss of focus should destroy the popup page.
The only truly persistent part of your extension that cannot be accidentally closed is the background script - that's where you should handle the chrome.identity
authorization. Send a message from your popup code that requests it.
Update: Note that you can't return a response to sendMessage
for the same reason - the popup no longer exists. Your logic should be to try to retrieve the token with interactive: false
every time the popup opens - and if that fails, request the background to initiate the interactive flow (and expect to be closed, so no sendResponse
).
Upvotes: 6