Meteor Capture

Two Factor Authentication

In this post we're going to cover adding two factor authentication to a Meteor application. I recently discovered a distinct lack of packages (none?) that provided this functionality so I created one! You can find it here: https://github.com/dburles/meteor-two-factor.

If you're not sure what two factor auth is exactly, this wikipedia article explains in detail what it's all about.

A couple of diagrams

Let's illustrate both regular and typical two factor authentication flow.

Regular authentication

Pretty self explanatory.

Regular authentication flow

Two factor authentication

Two factor authentication (as the name implies) requires an extra factor in authenticating with the application.

Implementation

The code examples we'll use throughout the rest of the article will be borrowed from this example app.

Step 1

First, add both accounts-password and dburles:two-factor packages:

$ meteor add accounts-password dburles:two-factor

Step 2

If you're adding two factor support to an existing application, replace Meteor.loginWithPassword with twoFactor.getAuthCode. Both functions are called identically.

Template.login.events({  
  'submit form'(event, template) {
    event.preventDefault();

    const user = template.$('#user').val();
    const password = template.$('#password').val();

    twoFactor.getAuthCode(user, password, error => {
      if (error) {
        return Session.set('loginError', error.reason);
      }

      Session.set('loginError', '');
    });
  }
});

After valid credentials have been passed in, the package will (by default) generate a 6 digit code that must be used in order to sign in.

Step 3

We use the reactive isVerifying function to display the verification code form. If it returns true; display the form (if you don't have one, make one!).

Template.body.helpers({  
  isVerifying() {
    return twoFactor.isVerifying();
  }
});

Step 4

Now we can capture the verification code and pass it to verifyAndLogin.

Template.verify.events({  
  'submit form'(event, template) {
    event.preventDefault();

    const code = template.$('#code').val();

    twoFactor.verifyAndLogin(code, error => {
      if (error) {
        return Session.set('verifyError', error.reason);
      }

      Session.set('verifyError', '');
    });
  }
});

Step 5 – Server side

We need a way to actually get the code to the user. For that, we'll define a function called sendCode. For the sake of the example we'll just log it to the terminal, in the real world this might send an SMS or an email. Make sure you define this only on the server.

twoFactor.sendCode = (user, code) => {  
  console.log(`Authentication code for '${user.username}' user is: ${code}`);
};

Conclusion

That's it!, there's a few more functions that we didn't cover here, you can find them documented on GitHub.

Just a random side note, I've received a lot of feedback on the blog with comments such as: "You can explain complex things in simple words :)". I really appreciate that! I always endeavour to write with brevity and clarity.

Thanks for reading!

Resources

Two factor package
https://github.com/dburles/meteor-two-factor

Example application
https://github.com/dburles/two-factor-example

comments powered by Disqus