Make tokens URL safe

Base64 encoding causes some issues when the token is URL encoded
as the = symbol is not a valid URL character. We replace any =
symbols with a - as this is valid in a URL, but is guaranteed
not to appear in a base64 string. This fix ensures that Ghost
password resets work with mail providers such as Mailgun that
add their own tracking redirects

closes #3872 (for real this time)
This commit is contained in:
Hugo Jobling 2014-11-20 11:24:31 +00:00
parent 0c38a839b0
commit 11a0f01e25

View File

@ -706,7 +706,7 @@ User = ghostBookshelf.Model.extend({
text = '';
// Token:
// BASE64(TIMESTAMP + email + HASH(TIMESTAMP + email + oldPasswordHash + dbHash ))
// BASE64(TIMESTAMP + email + HASH(TIMESTAMP + email + oldPasswordHash + dbHash )).replace('=', '-')
hash.update(String(expires));
hash.update(email.toLocaleLowerCase());
@ -715,13 +715,19 @@ User = ghostBookshelf.Model.extend({
text += [expires, email, hash.digest('base64')].join('|');
return new Buffer(text).toString('base64');
// it's possible that the token might get URI encoded, which breaks it
// we replace any `=`s with `-`s as they aren't valid base64 characters
// but are valid in a URL, so won't suffer encoding issues
return new Buffer(text).toString('base64').replace('=', '-');
});
},
validateToken: function (token, dbHash) {
/*jslint bitwise:true*/
// TODO: Is there a chance the use of ascii here will cause problems if oldPassword has weird characters?
// We replaced `=`s with `-`s when we sent the token via email, so
// now we reverse that change to get a valid base64 string to decode
token = token.replace('-', '=');
var tokenText = new Buffer(token, 'base64').toString('ascii'),
parts,
expires,