google / google-api-javascript-client

Google APIs Client Library for browser JavaScript, aka gapi.
Apache License 2.0
3.21k stars 1.06k forks source link

GoogleAuth.signIn promise is not resolved (new issue started 12th Feb) #277

Closed davemorrissey closed 7 years ago

davemorrissey commented 7 years ago

We use a customised login button on our site, to allow coexistence with other login methods. We trigger the OAuth popup with a call to GoogleAuth.signIn. Since Sunday 12th Feb, with no code changes on our end, this has stopped working - the Promise returned by this method is not resolved or rejected.

Our setup

Load https://apis.google.com/js/platform:client.js

Initialise the GoogleAuth object.

gapi.load('auth2', function() {
    window.gapiAuth2 = gapi.auth2.init({
        client_id: GAPI_CLIENT_ID,
        scope: 'email',
        cookiepolicy: 'single_host_origin',
        fetch_basic_profile: false
    });
});

On button click, call signIn.

    gapiAuth2.signIn({
        scope: 'email',
        prompt: 'select_account'
    }).then(function(googleUser) {
        console.log('Google interactive authorise succeeded');
    }, function() {
        console.log('Google interactive authorise failed');
    });

Expected behaviour

When the user authorises the request, the Google OAuth popup closes and the Promise returned by signIn is resolved. If the user rejects the request, the promise is rejected.

Actual behaviour

This behaviour is new since 12th Feb, without any code changes. The same code has worked reliably for 6 months.

  1. The user clicks our login button.
  2. The Google OAuth popup appears and an account chooser screen is displayed.
  3. The user selects an account and authorises the request.
  4. The popup closes.
  5. The Promise returned by signIn is neither resolved nor rejected.

Reproduced in Chrome, Safari, Firefox and Opera on macOS Sierra.

Attempted solutions

We've tried:

Note a standard login button added to the same page using a div with class g-signin2 does result in a successful callback to the supplied function when using the same script, client ID and configuration, however this method cannot be integrated with our authentication so it's not a suitable alternative for us.

davemorrissey commented 7 years ago

As of 11:40GMT this seems to have started working again, but very intermittently - it looks as though a fix is being rolled out. I'll leave this open for comment.

TMSCH commented 7 years ago

Hi @davemorrissey are you still observing the issue? Is there any logs in the console? Have you tried using "email profile" as scope instead of just email?

davemorrissey commented 7 years ago

I'm still seeing this on more than 50% of login attempts but it is not consistent. Yes I tried scope "email profile" but this made no difference and we've been using "email" successfully for months. There is nothing reported to the console, either on our page or in the OAuth poup window.

TMSCH commented 7 years ago

@davemorrissey Is there any network call that failed, in the main page?

To further debug (as I can't reproduce it myself), could you add this code:

window.addEventListener('message', function(event) {
  console.log(event.data);
});

before calling signIn (you can just copy and paste this snippet in the console before clicking the button), and let me know what's logged in the console?

davemorrissey commented 7 years ago

This is logged...

{
"method": "fireIdpEvent",
"params": {
    "type": "authResult",
    "clientId": "...",
    "id": "...",
    "authResult": {
        "id_token": "...",
        "login_hint": "...",
        "client_id": "..."
    }
},
"rpcToken": "..."
}

... but still the promise is not resolved.

davemorrissey commented 7 years ago

On the occasions when auth succeeds we get this second call:

{
"method": "fireIdpEvent",
"params": {
    "type": "sessionSelectorChanged",
    "newValue": {
        "hint": "...",
        "disabled": false
    },
    "domain": "...",
    "crossSubDomains": true
},
"rpcToken": "..."
}

It's this call which doesn't happen on the unsuccessful attempts.

TMSCH commented 7 years ago

Thanks @davemorrissey for the further information. I am investigating, but still cannot reproduce the issue so it is a bit difficult for me. I have tried Chrome and Firefox on Ubuntu and Mac OSX Sierra.

I'm using this snippet: http://jsbin.com/soxikemaku/1/edit?html,output with my clientId. Does it work for you there?

Are you using special Google accounts, like YouTube channels? Could you actually add the snippet of code I sent you at the top of your scripts so every message sent to the window are logged? There should also be another message received on successful login, which is confusing.

Is your code running on a website or some other environments (like Cordova)?

davemorrissey commented 7 years ago

I've tried that snippet with our client ID and it works reliably, even though we're still seeing intermittent failures with our own app. We're not using any special google accounts and the problem has been reported by some of our customers.

Our code runs on a website. You can try it here: https://remote.screentimelabs.com/#/login - if you use the Log in with Google button, no account will be created for you. If you reproduce the failure, the message Google popup closed unexpectedly will be logged to the console, and on successful attempts you'll see the "no account with this email" error.

There may be some interference with the Angular framework or one of the many libraries we load in, so I'm trying to narrow that down.

davemorrissey commented 7 years ago

I've worked out why this happens in our code. If the user closes the OAuth popup, the signIn promise is not rejected, so to detect this we added a popup watcher, which overrides window.open and checks whether the popup is closed unexpectedly, rejecting a promise if so. For reasons I can't explain, it seems this intermittently stops some of the messages being sent, but there's no pattern to it. The same code has worked reliably for several months but completely stopped working this weekend, and became intermittent on Monday.

It would be very useful if the library could reject the promise when the popup is closed, so we don't have to do this ourselves!

mattcarpenter commented 7 years ago

GoogleAuth.signIn() is failing to resolve or reject its promise in a project I'm working on.

We also have a popup watcher that overrides window.open but disabling this had no effect on the GoogleAuth.signIn() failure. In my case, gapi is throwing a Object {error: "idpiframe_initialization_failed", details: "Not a valid origin for the client."} exception upon initialization and no postMessage is occurring between my window and the OAuth popup. I'm calling signIn() from within an https://localhost:3001/ iframe nested within a top window site on a different FQDN.

For what it's worth, this worked prior to the 12th so it may be related to @davemorrissey's issue.

TMSCH commented 7 years ago

@davemorrissey we're actually going to push a new version soon that handles popup closing :)

@mattcarpenter have you whitelisted https://localhost:3001/ in your client_id origins?

mattcarpenter commented 7 years ago

@TMSCH I have both https://localhost:3001/ and http://localhost:3001 origins whitelisted, as well as the origin of the site loading the localhost:3001 iframe.

TMSCH commented 7 years ago

@mattcarpenter could you provide the network logs? I'm especially interested in calls to https://accounts.google.com/o/oauth2/iframerpc (please copy and paste the requests payloads and responses of these calls). If you don't see one with ?action=checkOrigin query parameter, please try to clear the cache and retry (or use an Incognito window). Thanks!

mattcarpenter commented 7 years ago

@TMSCH I've copied the request and response below. I can also provide a HAR with a sequence of all requests and responses if you'd find that useful.

Request:

GET /o/oauth2/iframerpc?action=checkOrigin&origin=https%253A%252F%252Flocalhost%253A3001&client_id=121699300049-9al32to5uojfvelraq612f11jcira9vu.apps.googleusercontent.com unknown
Referer: https://accounts.google.com/o/oauth2/iframe
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

Response

{
    "valid": false
}
TMSCH commented 7 years ago

Hmm it's weird, it does seem that https://localhost:3001 is not whitelisted for client_id 121699300049-9al32to5uojfvelraq612f11jcira9vu.apps.googleusercontent.com. Maybe remove the trailing slash from the whitelisted URL in the console?

mattcarpenter commented 7 years ago

@TMSCH That fixed it! Thanks for the assistance.

TMSCH commented 7 years ago

Awesome!

@davemorrissey @mattcarpenter closing the popup now rejects the Promise of signIn and grantOfflineAccess.

@davemorrissey please close the bug if you consider this issue solved! Thanks.

davemorrissey commented 7 years ago

Thanks, I'll try this tomorrow.

davemorrissey commented 7 years ago

That works well, thanks! Shame we couldn't work out what changed at the weekend but I'll close this now as it's not a problem for us any more.

TMSCH commented 7 years ago

Great @davemorrissey ! Agreed, I would have liked to understand that too. If it ever happens again, please copy paste the network logs too, that would be very helpful!

xiaosophiawang commented 7 years ago

@TMSCH Still getting the same error when I open quickstart.html in https://developers.google.com/google-apps/calendar/quickstart/js

Is there an older version of gapi I can link to to temporarily resolve this issue?

TMSCH commented 7 years ago

Hi @xiaosophiawang, have you tried the fixes proposed in this issue's thread? People had different issues and each one was solved.

If none work for you, could you provide the console logs, the network logs, as well as the environment (browser, platform, versions) under which you experience the issue?

Thanks!

melturphin commented 7 years ago

same problem going on... re-Verified that the while listed url is correct. Yesterday was working, today is not. Same code, no change in the api console.

{"method":"fireIdpEvent","params":{"type":"idpReady"},"rpcToken":"422554812.4174135"} {"id":"598-853235.8134723579","result":false,"rpcToken":"348651783.49495125"}

Object details : "Not a valid origin for the client." error : "idpiframe_initialization_failed"

network log REQUEST: https://accounts.google.com/o/oauth2/iframerpc?action=checkOrigin&origin=http%3A%2F%2Fkanban-ninja.s3-website-eu-west-1.amazonaws.com&client_id=547396580452-k45ss0rhgpb5jkhjcj8m9qqp5k5iajun.apps.googleUsercontent.com

network log RESPONSE: {"valid":false}

TMSCH commented 7 years ago

Hi @melturphin, can you make sure there is no typo in the URL entered in the console? It should be exactly (no trailing slash, no path):

http://kanban-ninja.s3-website-eu-west-1.amazonaws.com

For this client ID: 547396580452-k45ss0rhgpb5jkhjcj8m9qqp5k5iajun.apps.googleUsercontent.com

I am surprised this could have changed between yesterday and today. Would you have changed the deployment server, by any chance?

melturphin commented 7 years ago

Thanks for the quick answer. I'm experiencing unsteady behaviour. The easy solutions for the current stage of development is just to delete cretedials and create new ones. Now I'm having two authorized sources (some sort of localhost and the already mentioned url). From yesterday to today seems to keep working. But yesterday I had to delete it a couple of times.

I keep you posted if the problem reproduces.

madhu131313 commented 4 years ago

Same issue is repeating for but only when the app link is opened from facebook and instagram, during those times it uses webview and the promise is not returnining.

I have reproduced the issue here https://2k091.csb.app/

The page is staying in accounts.google.com page. Please help out

I have tested creating separate projects, different environments, still the issue is same. Screenshot_20200710-114938

julian-techzip commented 4 years ago

Hey everyone, if you are getting this error, try clearing the browser cache.

I'm using Firefox and clearing the cache updated the client to use the real whitelisted domains, not the cached ones I guess!

This problem bites me over and over again and I never remember the solution, so here's hoping I Google my own result in the future!

image