We have a Web application that allows usesr to log in with their Google accounts. Our application is written in Angular4 (latest build has 12.2.16 version). Recently we noticed that some users experience problems with Google login. After investigation, it was revealed the affected browsers are Firefox and Opera (in Chrome in Chrome, no issues were observed), this behavior only manifests when browsers fetch the https://apis.google.com/js/api.js for the first time, and for unknown reason no callback occurs (if page is refreshed and api.js is loaded from cache, everything works fine).
The problem started with recently released zone.js@0.11.5 (https://github.com/angular/angular/blob/master/packages/zone.js/CHANGELOG.md#0115-2022-03-03), and switching to the previous version (0.14.4) solves it, however I'd like to better understand the root cause, and whether it's an issue with zone.js, or our implementation is wrong and needs to be fixed.
The authentication is implemented as follows:
- index.html has the following script-tags at the top:
<script>
if ( typeof window != 'undefined' ) {
window.onGapiLoadCallback = function(){
window.gapiLoaded = true;
}
}
</script>
<script src="https://apis.google.com/js/api.js?onload=onGapiLoadCallback" async defer></script>
- There is an injectable service
@Injectable()
export class GoogleAuthService {
private googleAuth!: gapi.auth2.GoogleAuth;
private gapiLoadedPromise = new Promise<boolean>((resolve, _) => {
if ((window as any).gapiLoaded) {
resolve(true);
} else {
(window as any).onGapiLoadCallback = () => {
resolve(true);
};
}
});
public async initGoogleAuth(): Promise<void> {
await this.gapiLoadedPromise;
const pload = new Promise((resolve) => {
gapi.load('auth2', resolve);
});
return pload.then(async () => {
await gapi.auth2
.init({ client_id: environment.googleAuthClientId, scope: 'profile' })
.then((auth: gapi.auth2.GoogleAuth) => {
this.googleAuth = auth;
});
});
}
public authenticateUser(): Observable<gapi.auth2.GoogleUser> {
return from(this.initGoogleAuth()).pipe(
mergeMap(() => from(this.googleAuth.signIn()))
);
}
}
- A component where Google authentication is needed, calls
authenticateUser()
of the injected service, subscribes to it, and do whatever necessary with obtainedgapi.auth2.AuthResponse
object.
This implementation worked fine for a long time, but with zone.js@0.11.5
no callback happens, and hence the corresponding Promise object never resolves, leaving users with disabled Google login functionality.
I appreciate for any help or advice.