如何确定用户关闭了Google Auth2.signIn()窗口?

10
我正在使用这个来实现认证,并且在React中,当用户点击登录按钮并且auth2账户选择/登录窗口显示时,我当前正在显示一个加载图标。
但是,如果用户关闭该窗口,则似乎没有任何事件被触发,即返回一个promise的signIn()函数永远不会解决,我本以为谷歌会为此承诺返回错误。因此,我无法停止显示加载器图标并重新显示登录菜单。
我想知道是否有人有解决方案?

嗨Deep,你解决这个问题了吗? - Warrior
嘿,你是怎么做到的? - Pragati Dugar
3个回答

5

我尝试修改我的代码,调用Google OAuth 2.0窗口。
你只需要添加额外的AJAX方法,覆盖Google OAuth错误结果即可。

gapi.auth2.getAuthInstance().signIn()

将它更改为这个:
gapi.auth2.getAuthInstance().signIn().then(function(response){
    //If Google OAuth 2 works fine
    console.log(response);
}, function(error){
    //If Google OAuth 2 occured error
    console.log(error);
    if(error.error === 'popup_closed_by_user'){
        alert('Oh Dude, Why you close authentication user window...!');
    }
});

就是这样了...

如果您需要更多关于Google OAuth 2.0信息的详细信息,您可以访问此链接。
https://developers.google.com/api-client-library/javascript/samples/samples#authorizing-and-making-authorized-requests
JavaScript示例代码:
https://github.com/google/google-api-javascript-client/blob/master/samples/authSample.html


我们只是这样处理错误可以吗?每当打开新的弹出窗口时,我们是否必须显式取消挂起的 Promise,通过保留对它的引用来完成(类似于启动新的超时时删除超时引用)? - sayandcode

1
尽管API提供了一种机制来检测用户何时单击了拒绝按钮,但没有内置的方法来检测用户突然关闭了弹出窗口(或退出了他们的Web浏览器,关闭了计算机等)。如果您想要使用较少的范围重新提示用户(例如,您请求了“电子邮件”,但仅需要个人资料并允许用户在不向您提供电子邮件的情况下继续),则提供了“拒绝”条件。
如果登录回调的响应包含错误access_denied,则表示用户单击了拒绝按钮。
function onSignInCallback(authResult) {
  if (authResult['error'] && authResult['error'] == 'access_denied') {
    // User explicitly denied this application's requested scopes
  }
}

您应该能够实现登录而不必检测窗口是否关闭;几乎所有Google+示例应用程序都演示了这一点。简而言之,您应该避免使用旋转器,而是应在用户成功登录后隐藏已认证的UI。

虽然不建议这样做,但要实现检测弹出窗口关闭,您可以像覆盖全局window.open调用一样,然后在window.unload中检测或轮询窗口是否关闭而没有用户验证:

var lastOpenedWindow = undefined;
window.open = function (open) {
    return function (url, name, features) {
        // set name if missing here
        name = name || "default_window_name";
        lastOpenedWindow = open.call(window, url, name, features);
        return lastOpenedWindow;
    };
}(window.open);

var intervalHandle = undefined;
function detectClose() {
  intervalHandle = setInterval(function(){
    if (lastOpenedWindow && lastOpenedWindow.closed) {
      // TODO: check user was !authenticated
      console.log("Why did the window close without auth?");
      window.clearInterval(intervalHandle);
    }
  }, 500);
}

请注意,我已经实现的机制是不可靠的,并且容易出现竞态条件。

4
谢谢回复,但为什么Facebook可以提供这项服务?我的页面上有Facebook和Google身份验证选项,但如果用户关闭弹出窗口,Facebook的登录方法会解决失败。这对我来说似乎是Google方面的疏忽。旋转图标只是一种UX设计,用于向用户指示登录过程已开始(以防他们确实点击了另一个窗口并失去了登录窗口)。 - Deep

0
请将以下代码集成到您的index.html、default或main页面中的任何一个脚本标签中,然后您就可以根据URL控制您的window.open。
     Function.prototype.isNative = function() {
  return this.toString().indexOf('[native code]') > -1;

}

if (window.open.isNative()) {
    //   debugger;
     var originalOpen = window.open;
     window.open = function(URL, name, specs, replace) {
       console.log(originalOpen, 'originalOpen called');
         var newWindow = originalOpen(URL, name, specs, replace);
         console.log(originalOpen, 'originalOpen in new window called', URL, name, specs, replace);
        // debugger;
         if (URL.indexOf('https://accounts.google.com/') === 0) {
             var interval = setInterval(function() {
             //  console.log('Interval Started');
                 if (newWindow.closed) {
                     clearInterval(interval);
                     setTimeout(function() {
                       //Your conditional code goes here..
                        
                     }, 500);
                 }
             }, 1000);
         }
         return newWindow;
     }
 }

运行您的应用程序,上面是Google认证窗口,基于Facebook、LinkedIn或Microsoft,您可以更改URL条件。谢谢!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接