2017-12-14 15:26:48 +03:00
|
|
|
const crypto = require('crypto');
|
|
|
|
|
2018-06-22 21:28:01 +03:00
|
|
|
module.exports.generateFromContent = function generateFromContent(options) {
|
|
|
|
options = options || {};
|
|
|
|
|
2020-04-29 18:44:27 +03:00
|
|
|
const hash = crypto.createHash('sha256');
|
|
|
|
const content = options.content;
|
2018-06-22 21:28:01 +03:00
|
|
|
|
|
|
|
let text = '';
|
|
|
|
|
|
|
|
hash.update(content);
|
|
|
|
|
|
|
|
text += [content, hash.digest('base64')].join('|');
|
2018-10-30 11:45:51 +03:00
|
|
|
return Buffer.from(text).toString('base64');
|
2018-06-22 21:28:01 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
module.exports.generateFromEmail = function generateFromEmail(options) {
|
2018-04-25 12:56:45 +03:00
|
|
|
options = options || {};
|
|
|
|
|
2020-04-29 18:44:27 +03:00
|
|
|
const hash = crypto.createHash('sha256');
|
|
|
|
const expires = options.expires;
|
|
|
|
const email = options.email;
|
|
|
|
const secret = options.secret;
|
2018-04-25 12:56:45 +03:00
|
|
|
|
|
|
|
let text = '';
|
|
|
|
|
|
|
|
hash.update(String(expires));
|
|
|
|
hash.update(email.toLocaleLowerCase());
|
|
|
|
hash.update(String(secret));
|
|
|
|
|
|
|
|
text += [expires, email, hash.digest('base64')].join('|');
|
2018-10-30 11:45:51 +03:00
|
|
|
return Buffer.from(text).toString('base64');
|
2018-04-25 12:56:45 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
module.exports.resetToken = {
|
2017-12-14 15:26:48 +03:00
|
|
|
generateHash: function generateHash(options) {
|
|
|
|
options = options || {};
|
|
|
|
|
2020-04-29 18:44:27 +03:00
|
|
|
const hash = crypto.createHash('sha256');
|
|
|
|
const expires = options.expires;
|
|
|
|
const email = options.email;
|
|
|
|
const dbHash = options.dbHash;
|
|
|
|
const password = options.password;
|
|
|
|
let text = '';
|
2017-12-14 15:26:48 +03:00
|
|
|
|
|
|
|
hash.update(String(expires));
|
|
|
|
hash.update(email.toLocaleLowerCase());
|
|
|
|
hash.update(password);
|
|
|
|
hash.update(String(dbHash));
|
|
|
|
|
|
|
|
text += [expires, email, hash.digest('base64')].join('|');
|
2018-10-30 11:45:51 +03:00
|
|
|
return Buffer.from(text).toString('base64');
|
2017-12-14 15:26:48 +03:00
|
|
|
},
|
|
|
|
extract: function extract(options) {
|
|
|
|
options = options || {};
|
|
|
|
|
2020-04-29 18:44:27 +03:00
|
|
|
const token = options.token;
|
|
|
|
const tokenText = Buffer.from(token, 'base64').toString('ascii');
|
|
|
|
let parts;
|
|
|
|
let expires;
|
|
|
|
let email;
|
2017-12-14 15:26:48 +03:00
|
|
|
|
|
|
|
parts = tokenText.split('|');
|
|
|
|
|
|
|
|
// Check if invalid structure
|
|
|
|
if (!parts || parts.length !== 3) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
expires = parseInt(parts[0], 10);
|
|
|
|
email = parts[1];
|
|
|
|
|
|
|
|
return {
|
|
|
|
expires: expires,
|
|
|
|
email: email
|
|
|
|
};
|
|
|
|
},
|
|
|
|
compare: function compare(options) {
|
|
|
|
options = options || {};
|
|
|
|
|
2020-04-29 18:44:27 +03:00
|
|
|
const tokenToCompare = options.token;
|
|
|
|
const parts = exports.resetToken.extract({token: tokenToCompare});
|
|
|
|
const dbHash = options.dbHash;
|
|
|
|
const password = options.password;
|
|
|
|
let generatedToken;
|
|
|
|
let diff = 0;
|
|
|
|
let i;
|
2017-12-14 15:26:48 +03:00
|
|
|
|
|
|
|
if (isNaN(parts.expires)) {
|
2020-09-22 06:31:15 +03:00
|
|
|
return {
|
|
|
|
correct: false,
|
|
|
|
reason: 'invalid_expiry'
|
|
|
|
};
|
2017-12-14 15:26:48 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check if token is expired to prevent replay attacks
|
|
|
|
if (parts.expires < Date.now()) {
|
2020-09-22 06:31:15 +03:00
|
|
|
return {
|
|
|
|
correct: false,
|
|
|
|
reason: 'expired'
|
|
|
|
};
|
2017-12-14 15:26:48 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
generatedToken = exports.resetToken.generateHash({
|
|
|
|
email: parts.email,
|
|
|
|
expires: parts.expires,
|
|
|
|
dbHash: dbHash,
|
|
|
|
password: password
|
|
|
|
});
|
|
|
|
|
|
|
|
if (tokenToCompare.length !== generatedToken.length) {
|
|
|
|
diff = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = tokenToCompare.length - 1; i >= 0; i = i - 1) {
|
|
|
|
diff |= tokenToCompare.charCodeAt(i) ^ generatedToken.charCodeAt(i);
|
|
|
|
}
|
|
|
|
|
2020-09-22 06:31:15 +03:00
|
|
|
const result = {
|
|
|
|
correct: (diff === 0)
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!result.correct) {
|
|
|
|
result.reason = 'invalid';
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2017-12-14 15:26:48 +03:00
|
|
|
}
|
|
|
|
};
|