Обновите пользователя Angular Firebase после проверки электронной почты

Я пытаюсь найти способ обновить информацию о текущем зарегистрированном пользователе Firebase после успешной проверки их адреса электронной почты, чтобы они могли продолжать использовать веб-приложение Angular 15. У меня есть охранник, проверяющий проверенные электронные письма...

Общий процесс таков:

  1. Пользователь регистрируется с комбинацией электронной почты/пароля и входит в систему.
  2. onAuthStateChanged используется для хранения объекта User в localStorage.
  3. Пользователю отправляется ссылка для подтверждения по электронной почте
  4. Пользователь нажимает на ссылку подтверждения электронной почты и возвращается в веб-приложение в новой вкладке/окне.
  5. Учетная запись электронной почты Firebase Authentication пользователя проверена, но объект User не обновляется, чтобы отразить изменение.

Я пытаюсь определить, как лучше всего обновить текущего пользователя, чтобы «emailVerified» отображался как истинный. По сути, объект localStorage никогда не обновляется, чтобы отразить текущее состояние объекта Firebase Authentication User.

В сервисе auth.service.ts у меня есть следующее:

userData: any; //Save logged in user data

constructor(
    public afs: AngularFirestore, //Inject Firestore service
    public afAuth: AngularFireAuth, //Inject Firebase auth service
    public router: Router,   
    ) {
      // Listen for authentication changes and save User object to localStorage
      this.afAuth.onAuthStateChanged((user) => {       
        if (user) {
          this.userData = user;
          localStorage.setItem('user', JSON.stringify(this.userData));
          JSON.parse(localStorage.getItem('user')!);
        }
        else {
          localStorage.setItem('user', 'null');
          JSON.parse(localStorage.getItem('user')!);
        }
      });      
  }

  // Register the new user
  RegisterUser(userEmail: string, password: string) {
    return this.afAuth.createUserWithEmailAndPassword(userEmail, password)
      .then((result) => {
        this.SendVerificationMail();       
      });
  }

  // Send email verfificaiton
  SendVerificationMail() {   
    return this.afAuth.currentUser
      .then((u: any) => u.sendEmailVerification())
      .then(() => {
        this.router.navigate(['verify-email/sent']);
      });
  }

  // This is used within a AuthGuard to prevent un-verified accounts from continuing.
  get isVerified(): boolean {
    const user = JSON.parse(localStorage.getItem('user')!);
    return (user !== null && user.emailVerified !== false) ? true : false;
  }

В компоненте account-verify.component.ts у меня есть следующее для обработки пользовательских действий электронной почты.

//Use the 'oobCode' from the querystring to validate the email
handleVerifyEmail(actionCode: string) {       
   this.authService.afAuth.applyActionCode(actionCode).then(() => {               
        
        // This is where I would think I would update the user somehow.
        
        }).catch((error) => {                    
         //Handle Error
        });
      }

У меня есть мысленный блок относительно того, как убедиться, что у меня есть самая последняя информация из учетной записи аутентификации пользователя Firebase.

Я пробовал:

this.authService.afAuth.currentUser.then((user) => {
    user?.reload();
  });

Однако localStorage никогда не обновляется. Разве reload() не вызывает onAuthStateChange?

Любое понимание или лучшие способы справиться с этим приветствуются.

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
0
56
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Reload() не вызывает onAuthStateChange?

Как следует из названия, onAuthStateChanged срабатывает при изменении состояния авторизации. Изменение статуса проверки электронной почты не считается изменением состояния аутентификации.

Если вы хотите обнаружить все изменения, используйте одноименную функцию onIdTokenChanged, чтобы получать уведомления при изменении токена идентификатора.

Спасибо. Я изменил onAuthStateChanged на onIdTokenChanged, однако, когда я вызываю User.getIdToken(true), я не получаю новый токен. Должен ли я заставить пользователя выйти из системы и войти снова?

Mitchell Adams 12.05.2023 23:48

«когда я вызываю User.getIdToken(true), я не получаю новый токен». Я не уверен, почему нет, но я должен признать, что обычно я просто получаю результат, который я получаю от getIdToken(true) или вызываю reload() на пользовательский объект, а затем проверьте проверенное свойство текущего пользователя после завершения этого вызова.

Frank van Puffelen 13.05.2023 00:20

getIdToken(true)(firebase.google.com/docs/reference/js/… ) сам по себе не даст вам новую информацию (из-за того, как/когда она обновляется). Похоже, вам нужно вызвать reload() в связке. Я опубликую то, что я думаю, является решением. Большое спасибо за вторую пару глаз!

Mitchell Adams 13.05.2023 00:24

На самом деле не принято публиковать свой собственный ответ, когда мой ответ и последующие действия привели вас туда. ¯_(ツ)_/¯

Frank van Puffelen 13.05.2023 01:18

Извинения. Я подумал, что лучше всего опубликовать ответ с изменениями/решением кода, а не обновлять исходный пост. Никакого неуважения.

Mitchell Adams 13.05.2023 01:29

В auth.service.ts я изменил onAuthStateChanged на onIdTokenChanged.

this.afAuth.onIdTokenChanged((user) => {       
    if (user) {
        this.userData = user;
        localStorage.setItem('user', JSON.stringify(this.userData));
        JSON.parse(localStorage.getItem('user')!);
    }
    else {
        localStorage.setItem('user', 'null');
        JSON.parse(localStorage.getItem('user')!);
    }
});

И добавил функцию для перезагрузки пользователя и обновления токена:

RefreshUser() {       
    this.afAuth.currentUser.then((u: any) => {
        u.reload();
        u.getIdToken(true)
    });
}

В компоненте account-verify.component.ts я обновил функцию handleVerifyEmail, чтобы обновить пользователя после проверки электронной почты.

handleVerifyEmail(actionCode: string) {       
    this.authService.afAuth.applyActionCode(actionCode).then(() => {          
        this.authService.RefreshUser(); //Added this          
    }).catch((error) => {                    
      //Handle error
    });
}

Кажется, это работает.

Другие вопросы по теме