Created
January 26, 2016 07:42
-
-
Save camerondubas/0b388c4b709554919b89 to your computer and use it in GitHub Desktop.
Simple Node password reset without storing token in database (ES6)
This file contains 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
'use strict'; | |
var moment = require('moment'); | |
var bcrypt = require('bcrypt-nodejs'); | |
class PasswordService { | |
// Pass in user's email address that | |
// needs their password reset. | |
static resetPassword(email) { | |
// Promise for handling Success/Errors in outbound email call | |
return new Promise((resolve, reject) => { | |
// Token is is generated using the email and current time | |
// rounded to nearest 20 minute interval | |
var hashData = this.buildResetHash(email); | |
var resetToken = bcrypt.hashSync(hashData, bcrypt.genSaltSync(8)); | |
// Send user and email with a link to update password screen. | |
// The link should contain this hash and their email address as params | |
// Example link: `example.com/update-password?email=${email}&token=${resetToken}` | |
}); | |
} | |
// When user clicks the link in the email | |
// Send the token and email to this function | |
// to validate token and check if it's expired | |
static validateToken(token, email) { | |
var hashTries = 0; | |
// Attempts to validate the three most recent hashes | |
// rounded to the nearest 20 minute interval. | |
// This means that the token will be valid for one hour after creation | |
while (hashTries < 3) { | |
var hashKey = this.buildResetHash(email, (hashTries * 20)); | |
if (bcrypt.compareSync(hashKey, token)) { | |
return 'Hash matched'; | |
} | |
hashTries++; | |
} | |
return "Token is invalid or has expired"; | |
}); | |
} | |
static buildResetHash(email, offset) { | |
// Takes current time and offest to create a unique string | |
// to generate/compare a hash against. | |
var now = moment().subtract(offset || 0, 'minutes').format('YYYYMMDDHHmm'); | |
var rounded = Math.ceil(now / 10) * 10; | |
return email + rounded.toString(); | |
} | |
}; | |
module.exports = PasswordService; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment