0

So far in my project, I have set up a basic user management system. However, I'm unable to figure out a way to resend verification link after the user registers.

For example: When the user signs up, createUserWithEmailAndPassword is called which returns a promise. The promise is now resolved using then (or await) to which sendEmailVerification is called. This is all fine.

Note: The above flow is what I currently have implemented to for user management on the client side with Firebase Auth.

However, what if the user happens to delete this email or for whatever reason has no access to it at all. I want to be able to resend the link.

This uses Firebase Admin SDK on the backend and is an example of how to generate the verification email on the server-side. However, it appears that it is used in conjunction with account creation. In addition, it appears that Firebase Auth follows the same set of restrictions.

Not too sure where to go next and was wondering if there are any suitable workarounds.

Thanks.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
jeff
  • 490
  • 1
  • 6
  • 21
  • 1
    I'm not sure I understand the problem (and others with me it seems): what is keeping you from calling `sendEmailVerification()` again on the user object, for example with `FirebaseAuth.getInstance().getCurrentUser().sendEmailVerification()` on Android or firebase.auth().currentUser.sendEmailVerification() in JavaScript? – Frank van Puffelen Jun 25 '22 at 23:56

2 Answers2

0

Add a link to the login page to resend the verification email.

Then, trigger something along these lines:

sendEmailVerification() async {
  await FirebaseAuth.instance.currentUser?.sendEmailVerification();
}

Another option is to check during the login process whether the user verified the email. If not, resend it. Along these lines:

  signInWithEmailAndPassword(
    String email,
    String password,
  ) async {
    try {
      final credential = await FirebaseAuth.instance
          .signInWithEmailAndPassword(email: email, password: password);

      if (credential.user!.emailVerified == false) {
        await _sendEmailVerification();
        return ... // not verified, but email sent
      }

      return ... // success
    } on FirebaseAuthException catch (e) {
      return ... // error
    } catch (e) {
      return ... // error
    }
  }
Dabbel
  • 2,468
  • 1
  • 8
  • 25
  • The question states the that user cannot access the email address that they used to sign up with. Sending a verification email would not work. – Doug Stevenson Jun 25 '22 at 23:16
  • 1
    @DougStevenson My interpretation of the question differs. I read it as "no access to the email", not the account. – Dabbel Jun 25 '22 at 23:18
  • @DougStevenson Hi, that is what I meant. The email works, but user has no access to the email verification link (Perhaps it was permanently deleted). – jeff Jun 25 '22 at 23:19
  • Right, so sending a verification email to the original address that they used to sign in would not work because it's inaccessible. – Doug Stevenson Jun 25 '22 at 23:26
  • @DougStevenson Thought you got real question, no thing you can find in seconds. XD If user is logged in, just get `auth.currentUser.sendEmailVerification()` @jeff. Auth you can get from `getAuth()`. – Mises Jun 25 '22 at 23:27
  • I'm unclear how would it help to send a verification email to an address that the user does not have access to, as the question states? – Doug Stevenson Jun 25 '22 at 23:29
  • @DougStevenson he just don't know how to get again `currentUser` out of sign in function. – Mises Jun 25 '22 at 23:30
  • Have fun guys, I am out. Duh ... – Dabbel Jun 25 '22 at 23:31
  • @DougStevenson The user has access to the email address. However, I am referring to the ***initial*** email verification link the user receives upon registering. If that email is gone, I want to be able to send a new link to the registered email. – jeff Jun 25 '22 at 23:31
  • Are you saying that calling sendEmailVerification a second time doesn't work? – Doug Stevenson Jun 25 '22 at 23:33
  • @DougStevenson Hey sorry for all the confusion, but Dabbel solution fixed my problem. – jeff Jun 26 '22 at 01:49
0

The problem described here I think is as follows ( I am facing it as well):
=> some new User enters his Email and Password to create an account
=> we call createUserWithEmailAndPassword(email, password) => account can be found in firebase console under "Authentication" => in the app Auth.currentUser is NOT NULL. This is because acc. to documentatoin of "createUserWithEmailAndPassword" we read:
"@remarks
On successful creation of the user account, this user will also be signed in to your application."
=> Then we call sendEmailVerification(Auth.currentUser) - everything works, User Auth.currentUser gets his Email with verification link.

BUT. What if he does not click this link (maybe it went to spam)? He searcehs it, time passes, he maybe switches off the PC or closes the App. And after some time tries again: opens the App, tries to register again...
=> as he enters again the same E-mail he entered when he tried to register for the first time, our createUserWithEmailAndPassword() will give an error (because the User with such E-mail, even though it is not verified, is already in the database) => Auth.currentUser will be NULL(!!!)
=> if now you try to "REsend the verification E-Mail" with sendEmailVerification(Auth.currentUser) - it will not send anything. Because the user is null.

So, the way out of this situation is to generate verficication link based on the E-mail only and send it somehow to the User via E-mail:
https://firebase.google.com/docs/auth/admin/email-action-links#java_2

Asmik
  • 1
  • 1
  • If your understanding of the situation is correct, I think that the solution would be to check for existing accounts when an email is entered, and resend the link if it already exists. The important piece here would of course be detecting existing accounts associated with an email. firebase-admin/auth's Auth service has getUserByEmail. For example: const auth = getAuth(app); try { const user = await auth.getUserByEmail(email); return !!user.uid; } catch (err: any) { // If auth can't find the user, an error is thrown. Catch and ignore – Joseph Zabinski Jul 18 '22 at 14:57