UNPKG

2fatang

Version:

use for 2 factor authenticate with jwt

151 lines (122 loc) 4.18 kB
var express = require('express'); var bodyParser = require('body-parser'); var path = require('path'); var speakeasy = require('speakeasy'); var cookieParser = require("cookie-parser"); var nodemailer = require('nodemailer'); var jwt = require("jsonwebtoken"); var app = express(); app.use(bodyParser.json()) app.use(cookieParser()) app.use('/', express.static(__dirname + '/views')); const jwtKey = "my_secret_key"; const jwtExpirySeconds = 300; // manually set the user details for login verification // change the email and password here for login var user = { email: "joeleesuperweb@gmail.com", password: "test1" } // can change the smtp server details in here var transporter = nodemailer.createTransport({ host: 'smtp.gmail.com', port: 587, auth: { user: 'joeleewiserobot@gmail.com', pass: 'mytest!@#' } }); app.use(bodyParser.urlencoded({extended : true})); app.use(bodyParser.json()); app.get('/', function(req, res) { res.sendFile(path.join(__dirname + '/views/index.html')); }); app.post('/auth', function(req, res) { var email = req.body.email; var password = req.body.password; if (email && password) { if(email == user.email && password == user.password){ // compare the email password with mock data // Create a new token with the email in the payload // and which expires 300 seconds after issue const JWTtoken = jwt.sign({ email }, jwtKey, { expiresIn: jwtExpirySeconds, }) // set the cookie as the token string, with a similar max age as the token res.cookie("JWTtoken", JWTtoken, { maxAge: jwtExpirySeconds * 1000 }) const secret = speakeasy.generateSecret({length: 10}); // generate token in here var generatetoken = speakeasy.totp({ secret: secret.base32, encoding: 'base32' }); // setup email var mailOptions = { from: 'joeleewiserobot@gmail.com', to: email, subject: 'Email OTP', html: '<h1>Your OTP is '+generatetoken+'</h1>' }; // send token via email transporter.sendMail(mailOptions, function(error, info){ if (error) { console.log(error); } else { console.log('Email sent: ' + info.response); } }); // store the tempSecret of the logged in user user.twofactor = { tempSecret: secret.base32 }; res.sendFile(path.join(__dirname + '/views/otp.html')); } else { res.send('Incorrect Username or Password!'); res.end(); } } else { res.send('Please enter Email and Password!'); res.end(); } }); app.post('/verify', function(req, res){ // obtain the session JWTtoken from the requests cookies, which come with every request const JWTtoken = req.cookies.JWTtoken // if the JWTToken cookie is not set, return an unauthorized error if (!JWTtoken) { res.status(401).end() } var payload try { // Parse the JWT string and store the result in `payload`. // Note that we are passing the key in this method as well. This method will throw an error // if the JWTtoken is invalid (if it has expired according to the expiry time we set on sign in), // or if the signature does not match payload = jwt.verify(JWTtoken, jwtKey) } catch (e) { if (e instanceof jwt.JsonWebTokenError) { // if the error thrown is because the JWT is unauthorized, return a 401 error res.status(401).end() } // otherwise, return a bad request error res.status(400).end() } var verified = speakeasy.totp.verify({ secret: user.twofactor.tempSecret, //secret of the logged in user encoding: 'base32', token: req.body.token, window: 2 //accept tokens generated within ± 60 seconds of the server time }); if(verified){ res.redirect('/home'); } else { res.send('Invalid otp token, verification failed'); res.end(); } }); app.get('/home', function(req, res) { res.send('Welcome back'); res.end(); }); app.listen('3000', () => { console.log('App running on 3000'); });