├── .gitignore ├── README.md ├── package.json ├── views └── index.jade └── app.js /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | *.db 10 | data/*.db 11 | pids 12 | logs 13 | results 14 | 15 | node_modules 16 | npm-debug.log 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Twilio SMS + Node.js Phone Verification Example 2 | =========================== 3 | 4 | Find the full tutorial at twilio.com/blog 5 | [![githalytics.com alpha](https://cruel-carlota.pagodabox.com/848708d76bbde038f2166fc62756d656 "githalytics.com")](http://githalytics.com/jonmarkgo/TwilioNodePhoneVerification) 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TwilioNodePhoneVerification", 3 | "version": "0.0.1", 4 | "author": "Jon Gottfried ", 5 | "description": "a simple example of verifying a user's phone number using Node.js and Twilio", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/jonmarkgo/TwilioNodePhoneVerification.git" 9 | }, 10 | "dependencies": { 11 | "socket.io": "0.9.x", 12 | "twilio": "1.1.x", 13 | "express": "3.3.x", 14 | "jade": "0.34.x", 15 | "nstore": "0.5.x", 16 | "speakeasy": "1.0.x" 17 | }, 18 | "engines": { 19 | "node": ">=0.10" 20 | } 21 | } -------------------------------------------------------------------------------- /views/index.jade: -------------------------------------------------------------------------------- 1 | !!! 5 2 | html 3 | head 4 | script(src="/socket.io/socket.io.js") 5 | script(src="http://code.jquery.com/jquery-2.0.3.min.js") 6 | script 7 | var socket = io.connect(); 8 | 9 | $(function() { 10 | $("#register_button").on("click", function(event) { 11 | event.preventDefault(); 12 | socket.emit("register", { 13 | phone_number: $("#phone_number").val() 14 | }); 15 | }); 16 | 17 | $("#verify_button").on("click", function(event) { 18 | event.preventDefault(); 19 | socket.emit("verify", { 20 | phone_number: $("#phone_number").val(), 21 | code: $("#code").val() 22 | }); 23 | }); 24 | 25 | socket.on("code_generated", function(data) { 26 | $("#register").fadeOut(); 27 | $("#verify").fadeIn(); 28 | $("#update").fadeOut(); 29 | $("#register_instructions").fadeOut(); 30 | $("#verify_instructions").fadeIn(); 31 | }); 32 | 33 | socket.on("update", function(data) { 34 | $("#update").html(data.message); 35 | $("#update").fadeIn(); 36 | }); 37 | 38 | socket.on("reset", function(data) { 39 | $("#register_instructions").fadeIn(); 40 | $("#verify_instructions").fadeOut(); 41 | $("#update").fadeOut(); 42 | $("#register").fadeIn(); 43 | $("#verify").fadeOut(); 44 | }); 45 | 46 | socket.on("verified", function(data) { 47 | $("#register").fadeOut(); 48 | $("#verify").fadeOut(); 49 | $("#register_instructions").fadeOut(); 50 | $("#verify_instructions").fadeOut(); 51 | }); 52 | }); 53 | 54 | 55 | 56 | body 57 | strong#update(style="display: none") 58 | p#register_instructions Enter your phone number: 59 | p#verify_instructions(style="display: none") Enter your verification code: 60 | div#register 61 | form 62 | input(type="text")#phone_number 63 | input(type="submit", value="Register")#register_button 64 | div#verify(style="display: none") 65 | form 66 | input(type="text")#code 67 | input(type="submit", value="Verify")#verify_button -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var app = require('express')() 2 | , http = require('http') 3 | , server = http.createServer(app) 4 | , io = require('socket.io').listen(server) 5 | , nStore = require('nstore') 6 | , client = require('twilio')(process.env.account_sid, process.env.auth_token) 7 | , speakeasy = require('speakeasy'); 8 | 9 | var users = nStore.new('data/users.db', function () { 10 | console.log("Loaded users.db"); 11 | }); 12 | 13 | server.listen(3000); 14 | 15 | app.get('/',function(req,res){ 16 | res.render('index.jade') 17 | }); 18 | 19 | function createUser(phone_number, code, socket) { 20 | users.save(phone_number, {code: code, verified: false}, function (saverr) { 21 | if (saverr) { throw saverr; } 22 | client.sendSms({ 23 | to: phone_number, 24 | from: process.env.twilio_number, 25 | body: 'Your verification code is: ' + code 26 | }, function(twilioerr, responseData) { 27 | if (twilioerr) { 28 | users.remove(phone_number, function(remerr) {if (remerr) { throw remerr; }}); 29 | socket.emit('update', {message: "Invalid phone number!"}); 30 | } else { 31 | socket.emit('code_generated'); 32 | } 33 | }); 34 | }); 35 | } 36 | 37 | function checkVerified(socket, verified, number) { 38 | if (verified == true) { 39 | socket.emit('reset'); 40 | socket.emit('update', {message: "You have already verified " + number + "!"}); 41 | return true; 42 | } 43 | return false; 44 | } 45 | 46 | io.sockets.on('connection', function(socket) { 47 | console.log('socket.io connected'); 48 | socket.on('register', function(data) { 49 | var code = speakeasy.totp({key: 'abc123'}); 50 | users.get(data.phone_number, function (geterr, doc, key) { 51 | if (geterr) { 52 | createUser(data.phone_number, code, socket); 53 | } 54 | else if (checkVerified(socket, doc.verified, data.phone_number) == false) { 55 | socket.emit('update', {message: "You have already requested a verification code for that number!"}); 56 | socket.emit('code_generated'); 57 | } 58 | }); 59 | 60 | }); 61 | 62 | socket.on('verify', function(data) { 63 | users.get(data.phone_number, function (geterr, doc, key) { 64 | if (geterr) { 65 | socket.emit('reset'); 66 | socket.emit('update', {message: "You have not requested a verification code for " + data.phone_number + " yet!"}); 67 | } 68 | else if (checkVerified(socket, doc.verified, data.phone_number) == false && doc.code == parseInt(data.code)) { 69 | socket.emit('verified'); 70 | socket.emit('update', {message: "You have successfully verified " + data.phone_number + "!"}); 71 | users.save(data.phone_number, {code: parseInt(data.code), verified: true}, function (saverr) { if (saverr) { throw saverr; }}); 72 | } 73 | else { 74 | socket.emit('update', {message: "Invalid verification code!"}); 75 | } 76 | }); 77 | 78 | }); 79 | }); 80 | 81 | --------------------------------------------------------------------------------