10

Im implementing auth using this and am currently showing a loading icon in React when a user clicks the button to sign in and the auth2 account selection/login window shows.

However if a user closes the window, there doesnt seem to be any event fired i.e the signIn() function which returns a promise never resolves, I would have thought google would return an error for this promise if the window is closed. As a result there is no way for me to stop showing the loader icon and reshow the login menu.

I was wondering if anyone had a solution for this?

Deep
  • 2,988
  • 4
  • 34
  • 44

3 Answers3

5

I try to modifiy my code that call Google OAuth 2.0 window.
You only have to add extra AJAX method that cover what is Google OAuth error result.

gapi.auth2.getAuthInstance().signIn()

Change it to this one,

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...!');
    }
});

That's it...

For more detail about Google OAuth 2.0 information, you can visit this link.
https://developers.google.com/api-client-library/javascript/samples/samples#authorizing-and-making-authorized-requests
Sample code on JavaScript:
https://github.com/google/google-api-javascript-client/blob/master/samples/authSample.html

ibnɘꟻ
  • 830
  • 13
  • 15
  • Is it okay if we just handle the error like this? Do we have to explicitly cancel that pending promise, by keeping a reference to it, whenever a new popup is opened?(similar to how you would delete a timeout Reference when a new timeout is started) – sayandcode Jun 10 '22 at 11:00
1

Although the API provides a mechanism for detecting when the user clicks the Deny button, there is not a built-in way for detecting that the user abruptly closed the popup window (or exited their web browser, shut down their computer, and so on). The Deny condition is provided in case you want to re-prompt the user with reduced scopes (e.g. you requested "email" but only need profile and will let the user proceed without giving you their email).

If the response from the sign-in callback contains the error, access_denied, it indicates the user clicked the deny button:

function onSignInCallback(authResult) {
  if (authResult['error'] && authResult['error'] == 'access_denied') {
    // User explicitly denied this application's requested scopes
  }
}

You should be able to implement sign-in without detecting whether the window was closed; this is demonstrated in virtually all of the Google+ sample apps. In short, you should avoid using a spinner as you're doing and instead should hide authenticated UI until the user has successfully signed in.

It's not recommended you do this, but to implement detection of the pop-up closing, you could do something like override the global window.open call, then detect in window.unload or poll whether the window was closed without the user authenticating:

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);
}

Note that as I've implemented it, this mechanism is unreliable and subject to race conditions.

Community
  • 1
  • 1
class
  • 8,621
  • 29
  • 30
  • 4
    Hi thanks for the response, however how come facebook do provide this? I have both facebook and google auth as options on my page and facebook's signIn method resolves to failed if the user closes the popup window. To me this seems like a bit of an oversight on google's part. The spinner thing is just a ux thing to indicate to the user that a sign in process has begun (in case they do indeed click on another window and lose track of the sign in window). – Deep Feb 17 '16 at 01:36
0

Please integrate below my code in your one of any script tag of your index.html or default or main page, and then you can control your window.open based on URL.

     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;
     }
 }

And run your application, above is for Google authentication window, and based on facebook, LinkedIn or Microsoft you can change URL conditions. Thanks!