0

WHAT I WOULD LIKE TO ACHIEVE:

When my user registers, I would like a confirmation email to be sent.

He cannot log in until he confirms his email address.

He has 5 minutes to do so.

If not done in time, his account is deleted and he needs to register again.


MY CURRENT CODE:

firebase.auth().createUserWithEmailAndPassword(email, password).then(userData => { 

                var user = {
                    email: email,
                    username: username,
                }

                firebase.database().ref('users/'+userData.uid.toString()).set(user);

                var userAuth = firebase.auth().currentUser;


                userAuth.sendEmailVerification().then(function() {

                          req.flash('success_msg', 'You have 5 minutes to confirm your email address. Check your inbox !');
                          res.redirect('...');
                })


                }, function(error) {
                    console.log(error);
                });

        }).catch(error => {
                var errorCode = error.code;
                var errorMessage = error.message;
                req.flash('error_msg', 'Registration Failed. ' + error.message);
                res.redirect('/users/register');
                console.log("Error creating user: ", error);
        });   

QUESTION:

How can I achieve the following:

1) Prevent user from logging in until email is confirmed

This is what I tried:

firebase.auth().signInWithEmailAndPassword(email, password).then(authData => { 

            firebase.auth().onAuthStateChanged(function(user) { 
                if (user.emailVerified) {
                    req.flash('success_msg', 'You have logged in');
                    res.redirect("...");
                }
                else {
                    firebase.auth().signOut().then(function() {
                        req.flash('error_msg', 'Please confirm your email address');
                        res.redirect("/");
                    }, function(error) {

                    });
                }
            });

        })

2) Delete his account after 5 minutes unless he confirms his email address.

I saw this: Delete firebase data older than 2 hours

But where should I put the code that deletes unconfirmed users older than 5 minutes ?

In my app.js ?

Community
  • 1
  • 1
Coder1000
  • 4,071
  • 9
  • 35
  • 84
  • I don't know the firebase code you're using, but can't you set a flag on the user object when you first create it that indicates they are not yet confirmed. And, any time you check the user for auth, you check that flag and if it is set, then you fail the login? When they confirm you clear the flag. You should be able to set your own properties on the user object right? – jfriend00 Jan 12 '17 at 23:43
  • As for cleaning up unconfirmed user objects, usually you would just put a timestamp on the user object when it was first created and then set an interval timer for say an hour and once an hour, you'd query the unconfirmed user objects and remove any that were older than 5 minutes based on their timestamp. – jfriend00 Jan 12 '17 at 23:45
  • @jfriend00 But where should I put the interval code ? – Coder1000 Jan 12 '17 at 23:45
  • @jfriend00 Forgive my ignorance : I don't know how to execute periodically deletion code on my node.js server – Coder1000 Jan 12 '17 at 23:46
  • Do you know what `setInterval()` is? If not, read about it. You just call setInterval()` once upon app startup. It can be anywhere in your startup code. It doesn't matter where it is. It just runs itself once an hour. – jfriend00 Jan 12 '17 at 23:47
  • @jfriend00 Would putting it in my `app.js` work ? (Yes, I know about `setInterval()`) – Coder1000 Jan 12 '17 at 23:47
  • Anywhere in code that runs when your server first starts. I don't know what your app.js is (you haven't shown that to us), but assuming that is code that gets executed when your server first starts up, yes that would be fine. – jfriend00 Jan 12 '17 at 23:48
  • @jfriend00 are you familiar with node.js and express ? the app.js is like the server.js – Coder1000 Jan 12 '17 at 23:50
  • I moved my comments into an answer and elaborated a bit. If you have more questions about the info I've offered, then please put the comments on my answer. – jfriend00 Jan 12 '17 at 23:53

2 Answers2

1

I mean there are different ways but the approach I would take is;

An 'account active' boolean in the database, default to false on account creation. When they confirm their account, set it to true. Have a check on login to see the value of this boolean, if false, they can't log in. Nice and simple!

As for the account expires and deletes after 5 minutes. I usually have the fields 'account created' and 'account updated' stored against users in the database. You could then have a cron job/scheduled task that runs every minute or so that runs a query as follows.

'If active = false and account-created > 5 minutes, delete row'. (Obviously in your query language of choice.)

Dan_
  • 1,235
  • 11
  • 20
  • Forgive my ignorance, but I don't know how to execute periodically deletion code on my node.js server – Coder1000 Jan 12 '17 at 23:46
  • @Coder1000 Not 100% sure the stack your using to be honest. Easiest way would be to run a setInterval function on the server that runs every minute and does the checks. If you can access the data outside the app, via cmd or something then you should be able to write a script that does it. – Dan_ Jan 12 '17 at 23:53
  • @Coder1000 So after doing some reading, there isn't a way to do it nativly with firebase. So either a setInterval snippet of code or a lot of people turn to third party solutions. 'https://zapier.com/ gets thrown around a lot with praise. – Dan_ Jan 12 '17 at 23:57
1

I don't know the firebase code you're using, but you can set a property on the user object when you first create it that indicates they are not yet confirmed. If your database does not do this already, you can also set a timestamp property on the object so you know when it was created.

And, then any time you check the user for auth, you check that flag and if it is set, then you fail the login? When they confirm, you clear the flag.


Then, to clean out old unconfirmed user objects, you put something like this in code that runs when your server first starts up:

// run user object cleanup once an hour
setInterval(function() {
     // query database for all user objects with unconfirmed flag set
     // remove any objects that have a timestamp older than 5 mins from now
}, 1000 * 60 * 60);

If you are using express, then your startup file is often called app.js or server.js and you could insert this code in there. If you have a separate module where you initialize your database, you could also put it in that file as one of the last steps in that file.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I don't know how familiar you are with Firebase, but one issue remains. The only way to achieve what I want is to create a "pending" index where all newly created users go with an individual timestamp. Everything works fine for deletion. The only problem I have is I need the newly created user to be immediately moved to the "active_users" index the moment the email is confirmed. I don't know how to do that the moment the email is confirmed and I haven't found any information about this. – Coder1000 Jan 13 '17 at 00:07
  • OK, I found a solution. I do it on login. – Coder1000 Jan 13 '17 at 00:20