I'm working on implementing converting anonymous users to permanent users using GitHub auth provider.
The idea is that in my app, users are always automatically authenticated as anonymous users. Then, when they click the "Sign in with GitHub" button, basically what happens is that my app first tries to link that anonymous user to the GitHub credentials (which is basically a signin at the same time), but if the linking fails because the user already exists (e.g. has been linked before), it falls back to a normal sign in using GitHub.
I use firebase' APIs linkWithPopup(provider)
and signInWithPopup(provider)
. Both methods return a promise that resolves with the authenticated GitHub user which is great! However, it turns out that the user object that I get from linkWithPopup()
does not have the photoUrl
property set. It's always null
.
When I signInWithPopup()
straight away, without even trying to link, I also get a promise resolved with the user object and this one does have the photoUrl
set. So it looks like that there's a bug in linkWithPopUp()
.
Is this a known issue, or is this expected behaviour?
My code looks like this:
linkOrSignInWithGitHub(): Observable<User> {
let linkPromise = firebase.auth()
.currentUser
.linkWithPopup(new firebase.auth.GithubAuthProvider())
.then(result => result.user);
// If a user has been permanentely linked/authenticated already and tries
// to link again, firebase will throw an error. That's when we know that
// user credentials do already exist and we can simply sign in using GitHub.
return Observable.fromPromise(<Promise<any>>linkPromise).catch(error => this.signInWithGitHub());
}
And signInWithGitHub()
looks like this:
signInWithGitHub(): Observable<User> {
let loginPromise = firebase.auth()
.signInWithPopup(new firebase.auth.GithubAuthProvider())
.then(result => result.user);
return Observable.fromPromise(<Promise<any>>loginPromise);
}
So again, the code in itself works perfectly fine, it's just that I don't get the users photoURL
when using linkWithPopup()
.
To detect if a user is already logged in Firebase with JavaScript, we can call the onAuthStateChanged method. firebase. auth(). onAuthStateChanged((user) => { if (user) { // ... } else { // ... } });
If a user isn't signed in, CurrentUser returns null. Note: CurrentUser might also return null because the auth object has not finished initializing.
Every time a user signs in, the user credentials are sent to the Firebase Authentication backend and exchanged for a Firebase ID token (a JWT) and refresh token. Firebase ID tokens are short lived and last for an hour; the refresh token can be used to retrieve new ID tokens.
linkWithPopup does not modify the existing top level attributes (currentUser.email, currentUser.displayName, currentUser.photoURL, etc). It will only add a new providerData object in currentUser.providerData with the corresponding providerData you linked with. The top level data is set on sign up as you already notice.
You can update the top level data using that provider's data manually after linkWithPopup resolves.
currentUser.updateProfile({
photoURL: currentUser.providerData[indexOfGitHub].photoURL
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With