特定用户的 chrome.identity.launchwebauthflow 失败

jac*_*rre 2 javascript google-chrome-extension oauth-2.0

我研究这个问题已经有一段时间了,但没有成功。希望有人能对此有所了解!

我工作的地方认证/授权正在被谷歌的以外进行(谷歌的Chrome扩展(浏览器操作)chrome.identity.launchwebauthflowinteractive设置为true)。我们已经为某些用户(但不是全部)成功进行了身份验证/授权流程。以下是有趣的结果:

  1. 用户A点击扩展图标,点击授权按钮,成功获取验证码,将其兑换为访问令牌,并可以继续使用应用程序。
  2. 用户 B 点击扩展图标,点击授权按钮,扩展弹出关闭。它在交换访问令牌的身份验证代码之前失败。
  3. 用户 B 右键单击​​扩展图标,选择检查弹出窗口,单击授权按钮,成功获取验证码,将其交换为访问令牌,并可以继续使用应用程序。
  4. 用户 A 在带网络的安全模式下启动设备。用户 A 点击扩展图标,点击授权按钮,扩展弹出关闭。它在交换访问令牌的身份验证代码之前失败。
  5. 用户 A 在带网络的安全模式下启动设备。用户 A 打开一个选项卡并加载扩展程序的 url ( 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();
    }
});
Run Code Online (Sandbox Code Playgroud)

尝试应用后台代码解决方案后编辑的代码:

弹出脚本现在调用后台脚本:

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();
    }
});
Run Code Online (Sandbox Code Playgroud)

后台脚本响应弹出脚本。

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;

});
Run Code Online (Sandbox Code Playgroud)

Xan*_*Xan 5

launchWebAuthFlow从扩展弹出窗口调用是一个非常糟糕的主意。

此操作应该创建一个新窗口并专注于它。根据 Chrome 用户界面约定,这应该关闭扩展弹出窗口 - 并完全破坏该页面的 JavaScript 上下文。将不再有任何回调可调用。

这解释了为什么“检查弹出窗口”有帮助 - 这可以防止在失去焦点时关闭弹出窗口。此调试案例之外,此机制没有覆盖

这种弹出关闭行为可能因操作系统而略有不同,因此您可能没有在您的开发机器上看到它。但约定是明确的 - 任何失去焦点都应该破坏弹出页面。

唯一的 真正的坚持不能意外关闭的扩展程序的一部分是后台脚本 - 这就是您应该处理chrome.identity授权的地方。从请求它的弹出代码发送一条消息。

更新:请注意,sendMessage出于同样的原因,您无法返回响应- 弹出窗口不再存在。您的逻辑应该是在interactive: false每次弹出窗口打开时尝试检索令牌- 如果失败,则请求后台启动交互流(并期望关闭,所以没有sendResponse)。