7

Tutorial: Two-factor authentication with Meteor and TOTP

 3 years ago
source link: https://blog.meteor.com/tutorial-two-factor-authentication-with-meteor-and-totp-21d4a2f9ee51
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Tutorial: Two-factor authentication with Meteor and TOTP

Tutorial: Two-factor authentication with Meteor and TOTP

This is a guest post by Timo Horstschaefer, co-founder of Ledgy.com, the missing accounting software for your cap table—built with Meteor.

At Ledgy, we deeply care about our customer’s security and privacy. This is why we implemented a new two-factor authentication (2FA) system for Meteor.

This two-factor authentication system is based on the Time-based One-Time Password algorithm (TOTP), which is supported by a number of popular mobile apps like Google Authenticator, Duo and Authy.

Our implementation uses the fairly new otplib and adds a new login method to Meteor in order to pass the TOTP token along with the username and password.

This tutorial covers only the backend-code, meaning the methods for Meteor in order to activate 2FA and perform the login. The front-end is highly custom for each application and thus not covered by this tutorial.

The workflow for two-factor authentication goes as follows:

Setup

  1. Generate a secret key on the server, store it in the user’s profile and send it to the client.
  2. The user has to scan a QR code containing the secret with their 2FA app.
  3. The user enters a token generated by their 2FA app to confirm the setup.

Login

  1. The client calls the login method with a username and password.
  2. If the login is successful, but 2FA is enabled, the server returns 'two-factor-required', indicating that it needs further information.
  3. The client calls the login method again, now with username, password, and the time-dependent token from their 2FA app.

The Code

The first method we need to implement handles generating the secret and storing it in the user’s profile as services.twoFactorSecret:

Asking the server to generate a 2FA secret.
Image for post
Image for post
The Ledgy interface for activating two-factor authentication.

In the next step, using their 2FA app, the user scans the QR code which contains the secret key along with some metadata generated by otplib. If you use React, qrcode.react might be a good choice for generating the QR code on the client and prevent the browser from keeping the generated image in the cache. This isn’t a fully functional example, but on the front-end, this could look something like:

import otplib from 'otplib';
import QRCode from 'qrcode.react';const render = () => {
const otpauth = // String must be URI-encoded
otplib.authenticator.keyuri('Elon%20Must', 'Ledgy', secret); return (
<QRCode value={otpauth} level="H" size={256} />
);
}

In order to finalize 2FA activation, we’ll create a new server method that accepts a six-digit code from the user’s newly-activated 2FA app and, if correct when checked by the server, marks the account as “two-factor enabled”. This last verification step is important to ensure that the user has a functioning 2FA application, otherwise we’d end up locking them out of their account! We’ll store the fact that their account is two-factor enabled using a read-only boolean on the user’s record called twoFactorEnabled (i.e. Meteor.user().twoFactorEnabled).

We will never send the actual secret back to a client after the initial setup, so once the QR code is gone, it should never be shown to the user again.

We strongly recommend, that the actual image is generated on the client side to prevent potentially dangerous caching by the browser.

To enable 2FA, a valid token must be given to verify the local setup.

Logging In

Now that the setup part is done, let’s look at the login. Since Meteor doesn’t support a login method which accepts a TOTP code along with the password, we need to register our own. This is the centerpiece and most critical part of the two-factor authentication:

Note: For simplicity, this method only allows login by email. It currently does not support login by username or userId.

The only missing piece now is to call our new login method on the client. For this, we use the function Accounts.callLoginMethod(). The code will look somewhat like this (but again, it depends on your front-end):

Calling our new login method with email, password, and token.

Well, that’s it! Now you have modern, two-factor authentication using TOTP.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK