I am trying to find a way to refresh the current signed in Firebase user’s information after a successful validation of their email address so they can continue to use the Angular 15 web application. I have a guard checking for validated emails…
The overall process is:
- User registers with email/password combination and is signed in.
- onAuthStateChanged is used to store the User object in localStorage.
- User is sent an email verification link
- User clicks on email verification link and returns to the web app in a new tab/window.
- User’s Firebase Authentication email account is verified but the User object is not refreshed to reflect the change.
I’m trying to determine how best to update the current user to reflect the ’emailVerified’ as true. Essentially, the localStorage object never gets updated to reflect the current state of the Firebase Authentication User object.
In a auth.service.ts
service I have the following:
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;
}
Within a account-verify.component.ts
component I have the following to handle the Custom email actions.
//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
});
}
I’m having a mental block as to how to ensure I have the most current information from the User’s Firebase Authentication account.
I’ve tried:
this.authService.afAuth.currentUser.then((user) => {
user?.reload();
});
However localStorage never updates. Does the reload()
not trigger onAuthStateChange?
Any insight or better ways to handle this are appreciated.
2
Answers
In
auth.service.ts
I changedonAuthStateChanged
toonIdTokenChanged
.And added a function to reload the User and refresh the token:
Within the
account-verify.component.ts
component, I updated thehandleVerifyEmail
function to refresh the user after the email is validated.This seems to work.
As the name implies
onAuthStateChanged
triggers when the auth state has changed. A change in the email verification status is not considered an auth state change.If you want to detect all changes, use the similarly named
onIdTokenChanged
function to get notified when anything the ID token changes.