Skip to content

Instantly share code, notes, and snippets.

@mosampaio
Last active May 26, 2024 20:00
Show Gist options
  • Save mosampaio/205f91e88d20f2dbeb325a23af299625 to your computer and use it in GitHub Desktop.
Save mosampaio/205f91e88d20f2dbeb325a23af299625 to your computer and use it in GitHub Desktop.
Simple Phone Verification with Twilio, Node.js, Mongoose, and jQuery Raw

Please make sure you have set the following environment variables:

(This URL should be accessible thru the web. You can use Ngrok to help you if you are testing locally.)

export TWIML_SERVER_URL=https://www.example.org/twiml/

(This information can be found in your Twilio dashboard)

export TWILIO_ACCOUNT_SID=your-account-sid
export TWILIO_AUTH_TOKEN=your-auth-token
export TWILIO_PHONE_NUMBER=your-phone-number

How to run?

npm install
npm start
var express = require('express')
, path = require('path')
, cookieParser = require('cookie-parser')
, bodyParser = require('body-parser')
, app = express()
, mongoose = require('mongoose')
, Number = require('./number')
, twilio = require('twilio')
, twilioClient = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN)
, port = 3000;
app.set('views', path.join(__dirname));
app.set('view engine', 'pug');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
// routes
app.get('/', (req, res) => res.render('index'));
app.get('/static/main.js', (req, res) => res.sendFile(__dirname + '/main.js'));
app.get('/static/style.css', (req, res) => res.sendFile(__dirname + '/style.css'));
app.post('/call', (req, res) => {
var verificationCode = rand(100000, 999999);
var phoneNumber = req.body.phoneNumber;
Number.remove({'phoneNumber': phoneNumber}, (err) => {
Number.create({'phoneNumber': phoneNumber, 'verificationCode': verificationCode}, (err, number) => {
var params = {
to: req.body.phoneNumber,
from: process.env.TWILIO_PHONE_NUMBER, // Your twilio phone number
url: process.env.TWIML_SERVER_URL // full URL of /twiml route on your server
};
twilioClient.makeCall(params, (err, message) => {
if (err) {
console.log(err);
res.status(500).send(err);
} else {
res.send({'verificationCode': verificationCode});
}
});
});
});
});
app.post('/status', (req, res) => {
Number.findOne({'phoneNumber': req.body.phoneNumber, verified: true}, (err, number) => {
res.send({status: (number) ? 'verified' : 'unverified'});
});
});
app.post('/twiml', (req, res) => {
res.type('text/xml');
var verificationCode = req.body['Digits'];
var phoneNumber = req.body['Called'];
if (!verificationCode) {
res.send(new twilio.TwimlResponse().gather({numDigits: 6}, function() {
this.say('Please enter your verification code.');
}).toString());
} else {
Number.findOne({'phoneNumber': phoneNumber, 'verificationCode': verificationCode}, (err, number) => {
if (!number) {
res.send(new twilio.TwimlResponse().gather({numDigits: 6}, function() {
this.say('Verification code incorrect, please try again.');
}).toString());
} else {
number.verified = true;
number.save((err, number) => {
res.send(new twilio.TwimlResponse()
.say('Thank you! Your phone number has been verified.').toString());
});
}
});
}
});
var rand = function(low, high) {
return Math.floor(Math.random() * (high - low) + low);
};
app.listen(port, function () {
console.log('Listening on port ' + port);
});
mongoose.connect('mongodb://localhost/twilio-phone-verification');
doctype html
html
head
meta(http-equiv='Content-Type', content='text/html; charset=utf-8')
title Phone Verification by Twilio
script(type='text/javascript', src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js')
script(type='text/javascript', src='/static/main.js')
link(rel='stylesheet', href='/static/style.css')
body
form(id='enter_number')
p Enter your phone number:
p
input(type='text', name='phone_number', id='phone_number')
p
input(type='submit', name='submit', value='Verify')
div(id='verify_code')
p Calling you now.
p When prompted, enter the verification code:
h1(id='verification_code')
p
strong(id='status') Waiting...
$(document).ready(function(){
$("#enter_number").submit(function(e) {
e.preventDefault();
initiateCall();
});
});
function initiateCall() {
$.post("/call", { phoneNumber : $("#phone_number").val() },
function(data) { showCodeForm(data.verificationCode); }, "json");
checkStatus();
}
function showCodeForm(code) {
$("#verification_code").text(code);
$("#verify_code").fadeIn();
$("#enter_number").fadeOut();
}
function checkStatus() {
$.post("/status", { phoneNumber : $("#phone_number").val() },
function(data) { updateStatus(data.status); }, "json");
}
function updateStatus(current) {
if (current === "unverified") {
$("#status").append(".");
setTimeout(checkStatus, 3000);
}
else {
success();
}
}
function success() {
$("#status").text("Verified!");
}
'use strict';
var mongoose = require('mongoose');
var schema = new mongoose.Schema({
phoneNumber: { type : String , unique : true, required : true, dropDups: true },
verificationCode: Number,
verified: Boolean
});
module.exports = mongoose.model('numbers', schema);
{
"name": "simple-phone-verification-node",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"express": "~4.13.1",
"mongoose": "^4.5.9",
"pug": "^2.0.0-beta5",
"twilio": "^2.9.2"
}
}
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}
#verify_code {
display: none;
}
@acamino
Copy link

acamino commented Aug 31, 2016

@mosampaio could you remove the trailing slashes from the route methods?
e.g. https://gist.github.com/mosampaio/205f91e88d20f2dbeb325a23af299625/#file-app-js-L48

@acamino
Copy link

acamino commented Aug 31, 2016

Not sure if the apostrophes are needed here. Could you double check it please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment