Last active
March 29, 2018 17:31
-
-
Save MikeLuDev/6429cb8d6b1f4fbf4e613cd1143b51ce to your computer and use it in GitHub Desktop.
Password recovery implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//=============================================================================== | |
// RECOVERY CALLS | |
//=============================================================================== | |
const express = require('express'); | |
const app = express(); | |
const crypto = require('crypto'); | |
app.get('/recovery', (req, res) => { | |
let messages = req.session.flash; | |
req.session.flash = null; | |
let recovery_page = ReactDOMServer.renderToString( | |
React.createElement(RecoveryPage, { | |
name: 'Tokes - Password Recovery', | |
dashboard: false, | |
messages: messages }) | |
); | |
res.send(recovery_page); | |
req.session.flash = null; | |
}); | |
app.post('/recovery', (req, res) => { | |
const crypto = require('crypto'), | |
algorithm = process.env.ENCRYPT_ALGORITHM, | |
password = process.env.ENCRYPT_PASSWORD; | |
let email = req.body.email; | |
// Generate recovery token with crypto | |
let recoveryToken = crypto.randomBytes(60).toString('hex'); | |
// Ensure user email and recovery token exist | |
if (email && recoveryToken) { | |
// Query string | |
let emailQuery = `SELECT * FROM users WHERE email='${email}'` | |
// Query database by user email | |
db.query(emailQuery, function(err, rows) { | |
if (err) { | |
console.log(err); | |
req.flash('errorMessages', 'There was an error'); | |
res.redirect('/'); | |
} | |
// If the user exists, update user rows with recovery token and flash success | |
if (rows.length) { | |
let user = new User(rows[0]); | |
user.update({ | |
recovery_token: recoveryToken | |
}); | |
user.SendConfirmationEmail(); | |
req.flash('appMessages', `We've sent an email to you with instructions to reset your password.`); | |
res.redirect('/'); | |
} else { | |
req.flash('errorMessages', `Invalid email address. Please try again.`); | |
res.redirect('/recovery'); | |
} | |
}); | |
} else { | |
req.flash('errorMessages', 'There was an error generating your recovery email'); | |
res.redirect('/'); | |
} | |
}); | |
// No token validation here to prevent sniffing based on url | |
app.get('/recovery/:recovery_token', (req, res) => { | |
let messages = req.session.flash; | |
req.session.flash = null; | |
let recoveryToken = req.params.recovery_token; | |
const reset_page = ReactDOMServer.renderToString( | |
React.createElement(ResetPage, { | |
name: 'Tokes - Reset Password', | |
dashboard: false, | |
messages: messages, | |
recovery_token: recoveryToken | |
}) | |
); | |
res.send(reset_page); | |
}); | |
app.post('/password/new', (req, res) => { | |
let recoveryToken = req.body.recovery_token; | |
let email = req.body.email; | |
let newPassword = req.body.new_password; | |
let verifyPassword = req.body.verify_password; | |
// Ensure passwords match each other | |
let passwordsMatch = (newPassword === verifyPassword); | |
if (!passwordsMatch) { | |
res.send({'status': 'error', 'message': 'The passwords you submitted did not match'}); | |
} | |
else if (passwordsMatch) { | |
// Query for both email and recovery token | |
let recoveryQuery = `SELECT * FROM users WHERE email='${email}' AND recovery_token='${recoveryToken}'`; | |
db.query(recoveryQuery, function(err, rows){ | |
if (err) { | |
console.log(err); | |
res.send({'status': 'error', 'message': 'There was an error'}); | |
} | |
// If match is found | |
if (rows.length) { | |
let user = new User(rows[0]); | |
// Update user with new encrypted password, reset recovery token to null | |
user.update({ | |
encrypted_password: user.generateHash(newPassword), | |
recovery_token: null | |
}).then( () => { | |
res.send({'status': 'success', 'message': 'Your password has been updated! You may now log in.'}); | |
}).catch( () => { | |
res.send({'status': 'failure', 'message': 'There was an error updating your password'}); | |
}); | |
} else { | |
res.send({'status': 'error', 'message': 'Invalid email address or recovery link'}); | |
} | |
}); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment