In my app I'd like to show avatar of logged Facebook user. I haven't found any elegant solution.
To show an avatar of user you need to provide two things: user_id
and accessToken
. user_id
is available any where via AngularFireAuth
service, but I haven't found accessToken
anywhere but in logging method.
I'm using "@angular/fire": "6.0.3"
, and login with redirect method.
My solution. When I log in user, the accessToken
is stored in local storage. It is because getRedirectResult()
method returns credentials only while user is logging. When user is already logged in, method doesn't return credentials.
ngOnInit(): void {
this.progress.show();
this.angularFireAuth.getRedirectResult()
.then((uc: any) => {
const token = uc?.credential?.accessToken;
if (token) {
localStorage.setItem('fbuser', token);
this.router.navigateByUrl('/');
}
this.progress.hide();
});
}
loginFacebook(): void {
const provider = new auth.FacebookAuthProvider();
this.angularFireAuth.signInWithRedirect(provider);
}
and when I need to display the image:
constructor(private auth: AngularFireAuth) { }
this.user$ = this.auth.user;
this.avatarSrc$ = this.user$.pipe(
map(u => u.providerData[0].uid),
map(uid => {
const accessToken = localStorage.getItem('fbuser');
return `http://graph.facebook.com/${uid}/picture?type=square&access_token=${accessToken}}`
}),
);
I'm not sure it is best solution, especially use of local storage.
Have some one had similar problem and found better way?
We use firestore in our app to store the avatar.
On sign in with a provider, we set a user document in firestore (when it's a new user) and we copy the provider avatar url into the user data:
ngOnInit(): void {
this.progress.show();
this.angularFireAuth.getRedirectResult()
.then((uc: any) => {
// skip data creation if user is not new
if (!uc.additionalUserInfo.isNewUser) { return Promise.resolve(); }
const user = uc.user;
return this.angularFirestore.collection('user_collection').doc(user.uid).set({
avatarURL: user.photoURL || '',
email: user.email || '',
displayName: user.displayName || ''
});
})
.then(() => {
this.progress.hide();
this.router.navigateByUrl('/');
});
}
loginFacebook(): void {
const provider = new auth.FacebookAuthProvider();
this.angularFireAuth.signInWithRedirect(provider);
}
Then in the app, with the authState, we fetch the user data in DB containing the avatar url:
constructor(private auth: AngularFireAuth) { }
this.authState$ = this.auth.authState;
this.user$ = this.authState$.pipe(
switchMap(state => {
return (!!state) ?
this.angularFirestore.collection('user_collection').doc(state.uid).valueChanges() :
of(null);
})
);
this.avatarSrc$ = this.user$.pipe(
map(user => user.avatarURL)
);
Yes, it seems legite. Meanwhile I consulted this on the angularfire's github and the answer is the same. Thanks.