Skip to main content
  • Node
  • Ruby
  • Python
  • PHP
  • .NET

Overview

This guide shows how to set up SMS-based two-factor authentication (2FA) using Plivo’s APIs and Node.js. Authentication with a one-time password (OTP) delivered to users via SMS is an effective way to secure your application.

Set up the demo application

First, clone the 2FA demo repository from GitHub and install the dependencies.
git clone [https://github.com/plivo/2fa-node-demo.git](https://github.com/plivo/2fa-node-demo.git)
cd 2fa-node-demo
npm install
Next, edit config.js. Replace the auth placeholders with your credentials from the Plivo console. Add your Plivo phone number and set the phlo_id to null.

A review of the code

Here’s a walk-through of the key functions in the demo application.

Step 1: Generate the OTP

This function generates a random six-digit one-time password.
const code = Math.floor(100000 + Math.random() * 900000);

Step 2: Send an SMS with the OTP

This function sends an SMS message containing the OTP to the user’s number using Plivo’s Send Message API.
sendVerificationCode_sms(DstNumber, Message) {
    const code = Math.floor(100000 + Math.random() * 900000);
    this.client.messages.create({
        src: this.app_number,
        dst: DstNumber,
        text: Message.replace('__code__', code),
    });
    return code;
}

Failover: Make a voice call with the OTP

If the user doesn’t receive the SMS, they can request the OTP via a voice call using Plivo’s Make a Call API.
sendVerificationCode_call(DstNumber) {
    const code = Math.floor(100000 + Math.random() * 900000);
    this.client.calls.create(
        this.app_number, // from
        DstNumber, // to
        '[https://twofa-answerurl.herokuapp.com/answer_url/](https://twofa-answerurl.herokuapp.com/answer_url/)' + code // answer_url
    );
    return code;
}

Step 3: Verify the OTP

This function checks if the OTP entered by the user matches the one stored in Redis.
router.get('/checkcode/:number/:code', function(req, res) {
    const number = (req.params.number);
    const code = (req.params.code);
    redisClient.get(`number:${number}:code`, function(err, originalCode) {
        if (originalCode == code) {
            redisClient.del(`number:${number}:code`);
            res.send(JSON.stringify({
                'status': 'success',
                'message': 'Codes match, number verified'
            }));
        } else {
            res.send(JSON.stringify({
                'status': 'failure',
                'message': 'Codes do not match'
            }));
        }
    });
});

Test

First, start the Redis server.
redis-server
Then, run the application.
node app.js
Use a tool like ngrok to expose your local server to the internet, then open the ngrok URL in your browser to see the demo app.