angular / angularfire

Angular + Firebase = ❤️
https://firebaseopensource.com/projects/angular/angularfire2
MIT License
7.66k stars 2.19k forks source link

getRedirectResult() always returns null - Unable to retrieve idToken after signInWithRedirect() #3335

Open falk-stefan opened 1 year ago

falk-stefan commented 1 year ago

Version info

Angular: 15

Firebase: 9

AngularFire: 7.5.0

How to reproduce these conditions

Steps to set up and reproduce

Note: I am testing this locally and on a mobile device. In both cases I am using Chrome. The application is hosted locally running ng serve --watch --ssl --host 0.0.0.0 which means the SSL certificate is not valid. I mention this in case it is relevant.

I'm simply calling signInWithRedirect() and install an APP_INITIALIZER provider to make sure the idToken is loaded as the app starts.

However, the idToken (as well as the credentials) are always null/undefined and I have no idea why. Could be related to (https://github.com/angular/angularfire/issues/3208).

public signInWithGoogle() {
  return signInWithRedirect(this.auth, new GoogleAuthProvider());
}
export const AUTH_ID_TOKEN_INITIALIZER_PROVIDER: Provider = {
  provide: APP_INITIALIZER,
  deps: [NGXLogger, AuthService],
  multi: true,
  useFactory: (logger: NGXLogger, authService: AuthService) => {
    return async () => {
      logger.info("Initializing App: Waiting for (API) idToken");
      const credentials = await getRedirectResult(authService.auth);
      console.log(credentials);  // Is already null
      const idToken = await credentials?.user.getIdToken();
      console.log(idToken);
      if (idToken) {
        return idToken;
      }
      await authService.init();  // <-- Implementation below (put it here for testing)
      return firstValueFrom(authService.idToken$);
    }
  },
};

I tried a different approach after reading that we have to wait for onAuthStateChanged() to fire and only after that we're supposed to fetch the idToken. The implementation looked like this (with the same result however):

async init() {
  this.logger.debug("Checking for token from redirect");
  const credentials = await getRedirectResult(this.auth);
  this.idToken = await credentials?.user.getIdToken();

  await this.auth.onAuthStateChanged(
    async () => {
      const credentials = await getRedirectResult(this.auth);
      this.idToken = await credentials?.user.getIdToken();
      console.log("inner");
      console.log(this.idToken);
    }
  );
  console.log("outer");
  console.log(this.idToken);
}

Expected behavior

Receive a valid idToken after beind redirected.

Actual behavior

Credentials & token are null / undefined.

google-oss-bot commented 1 year ago

This issue does not seem to follow the issue template. Make sure you provide all the required information.

rgant commented 1 year ago

Are you using incognito windows? The redirect only works if you allow third party access to storage, which isn't allowed in Chrome incognito windows. At least that was my case.

falk-stefan commented 1 year ago

@rgant No, I'm not using incognito here. It's neither working on mobile nor on desktop.

I noticed that the redirect works if I am using the emulators - for whatever reason - but emulators are breaking the Spring Boot authentication chain.

It's painfully annoying..

rgant commented 1 year ago

I just implemented this myself, and best I can tell it is working just fine.

My advice would be to join the Angular Community Discord and ask there.

What I am seeing in your code above is that you are always checking getRedirectResult which will emit an object with null credentials and user properties if the signInWithRedirect call either wasn't made in the past, or wasn't able to write to storage. My solution for this was to set a flag in storage and then only call getRedirectResult if the flag was there. But I was using a specific page for my redirect login.

Note that Google's own example code expects you to have to test that the credential property is truthy.

falk-stefan commented 1 year ago

@rgant Can you elaborate what your exact setup is and what it is that is working on your end?

getRedirectResult(), as stated, only works when I am using the Authentication Emulator in which case I'll get a non-null UserCredential which holds a "valid" token. However, this token doesn't fly with my backend as it cannot be verified under https://securetoken.google.com for obvious reasons.

This is annoying because I cannot just use local test-accounts on my client and test client/server together.

The core I posted above looks "weird" and lacks some checking because it is me jolting everything back and forth hoping it'll work somehow.

So.. is getRedirectResult() workign for you with and without emulators?

jhades commented 1 year ago

I'm also getting the same issue, I can't use signInWithRedirect. I get a null user profile after the redirect. Did you find out the root cause? I'm using an authDomain that is on a different subdomain where the login page is hosted.

The user profile should propagate across different domains of the same domain, right?

falk-stefan commented 1 year ago

@jhades I'm still struggling with this.

ohabash commented 11 months ago

also struggling with this. my user is logged

import { AngularFireAuth } from '@angular/fire/auth';
private afAuth: AngularFireAuth,
return this.afAuth
            .signInWithPopup(provider)
            .then((userCredentials) => this.loginSuccess(userCredentials));

now in another part of the app at need these credentials again. so im trying

const result = await this.afAuth.getRedirectResult();
console.log(`🚀 => AuthInterceptor => result:`, result) // always null

but the result is {user: null}

IliaIdakiev commented 7 months ago

I'm also experiencing the same issue, the getRedirectResult() was working when I started developing the project and then all of a sudden it started returning null

marius-eichenberg commented 5 months ago

@falk-stefan, are you, by any chance, protecting a route with an auth guard?

falk-stefan commented 5 months ago

@marius-eichenberg Uh, that's a good point. I can't really tell right now as I am on a different project currently, but there's a possibility an auth-guard interferred here.

servefast-cto commented 3 months ago

Same issue with me its becoming annoying always something not working with the emulator

Romanovskyi2137 commented 1 month ago

so, still no solution right?) actually i have the same problem, BUT, earlier my implementation worked well, but now its dont, i have null after come back to login page after redirect. magic