Warm tip: This article is reproduced from serverfault.com, please click

What is proper way to show Facebook avatar using AngularFire

发布于 2020-12-03 16:19:29

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?

Questioner
Walter Luszczyk
Viewed
0
Quentin Fonck 2020-12-09 01:39:08

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)
);