0

I've created a login and registration screen that works with my Flutter app, using Firebase as the backend authentication service. I'm able to switch between the login, registration and reset password screens well.

The Issue

At the moment, the registration screen accepts any email address that is entered, whether or not it is real. For example, if I were to type in gvevg@gverwbgw.com, it would allow the user to register. This is obviously an issue, when it comes to fake accounts and spam etc.

The Aim

I would basically like to be able to edit my code, to automatically generate an email address verification email, which prevents the user from signing in, before their email address has been verified. The code I have made uses a Future, FirebaseAuth and async/await to make this happen.

My Current Code

Firstly, I define an AuthBase abstract class, that creates the 'createUserWithEmailAndPassword' function (amongst others) as follows:

abstract class AuthBase {
  Stream<User> get onAuthStateChanged;
  Future<User> currentUser();
  Future<User> createUserWithEmailAndPassword(String email, String password);
}

Then, I create an Auth function, that implements AuthBase, gets the current user from Firebase and creates the registration Future function, as follows:

class Auth implements AuthBase {
  final _firebaseAuth = FirebaseAuth.instance;

  // This creates the user ID token variable (if one doesn't already exist) which is then populated using one of the login methods.
  User _userFromFirebase(FirebaseUser user) {
    if (user == null) {
      return null;
    }
    return User(uid: user.uid);
  }

  // This helps to get the user from Google Firebase, noting if there is or isn't a user with those login details already.
  @override
  Stream<User> get onAuthStateChanged {
    return _firebaseAuth.onAuthStateChanged.map(_userFromFirebase);
  }

  // This identifies the current user, who is logged in at the time.
  @override
  Future<User> currentUser() async {
    final user = await _firebaseAuth.currentUser();
    return _userFromFirebase(user);
  }

  // This creates the user account for an email-and-password sign-in, with firebase, if it doesn't already exist.
  @override
  Future<User> createUserWithEmailAndPassword(
      String email, String password) async {
    final authResult = await _firebaseAuth.createUserWithEmailAndPassword(
        email: email, password: password);
    return _userFromFirebase(authResult.user);
  }
}

My Question

How do I edit my code, so that it allows me to implement email verification automatically for any user that wants to sign in with email? I believe the sendEmailVerification() function must use FirebaseUser, although I am not sure how to implement it here. I would appreciate any help. Thanks!

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
James
  • 669
  • 1
  • 10
  • 21
  • Email+password authentication requires nothing more than that the user knows the combination of email+password. It doesn't in itself require the email address to be verified to sign in. If you want the email address to be verified before allowing access to other data, you can do that by checking the [user's token for the `email_verified` claim](https://firebase.google.com/docs/reference/security/database#authtoken) for example in the security rules of your database. – Frank van Puffelen Feb 18 '20 at 14:48
  • Also see https://stackoverflow.com/q/36943350, https://stackoverflow.com/a/48029049, https://stackoverflow.com/a/56784168, https://stackoverflow.com/a/57343047 – Frank van Puffelen Feb 18 '20 at 14:52

1 Answers1

4

Email+password authentication requires nothing more than that the user knows the combination of email+password. It doesn't in itself require the email address to be verified to sign in. If you want the email address to be verified before allowing access to other data, you can do that by checking the user's token for the email_verified claim for example in the security rules of your database.

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks! So, provided I can add a verification using `auth.token.email_verified == true` then this would work, without having to set up an automatic email generation from the app/firebase? Presumably it works because anyone who has set up an email that they're using would have had to verify it initially, so fake and spam emails (which haven't been verified) would be rejected? – James Feb 18 '20 at 19:34
  • I have no idea what you mean there. If a user verifies their email address through Firebase Authentication's built-in mechanism, their `auth.token.email_verified` will be set to `true`. You can check for this in your code and in the security rules of Realtime Database, Firestore, and Storage, to ensure the user can't access anything in those services until they've verified their email address. – Frank van Puffelen Feb 18 '20 at 19:41
  • I understand now. I'm going to give it a go soon and see if I can get it to work. The examples I had seen prior to your information basically prevented registration until the user has verified their email address - hence using an automatically-generated email verification email. – James Feb 18 '20 at 21:00