11

I'm using a node.bcrypt.js hash returning hex numbers in node.js for a password reset token.

user.reset_password_token = require('crypto').randomBytes(32).toString('hex'
);

Should I also base64 encode the token before I pass it around in urls (ie: link reset email)?

Is there any benefit to doing this?

I seem to recall base64 encoding can contain forward slashes which would mess up the path:

   var token = user.reset_password_token;

   //is there any benefit to doing base64 encoding?
   var encoded_token = new Buffer(token).toString('base64');

   var reset_link = 'http://example.com/reset/'+ encoded_token;
   sendResetLink( reset_link );
chovy
  • 72,281
  • 52
  • 227
  • 295
  • 2
    http://stackoverflow.com/questions/1374753/passing-base64-encoded-strings-in-url (no, points out non-URL safe characters), http://stackoverflow.com/questions/1228701/code-for-decoding-encoding-a-modified-base64-url (talks about modified version) –  Sep 27 '12 at 22:37
  • 1
    Here is an *old* answer I wrote [for an alternative way to address this](http://stackoverflow.com/questions/4395706/base64-encoding-that-doesnt-use-plus-or-equals-characters/4395900#4395900) that only requires a trivial pre/post replacement step for a variant base64 escape-encoding that doesn't require non-alphanumeric ASCII characters. –  Sep 27 '12 at 22:44
  • If your token is simply the hex representation of 32 random bytes, there is no need to do any additional encoding. Hex characters (0-9A-F or 0-9a-f) are perfectly fine as-is. Personally I would not bother with double encoding. Remember: those Hex characters are already an encoding of the binary data. – Frugal Guy Sep 22 '22 at 17:07
  • As to your questions about Base64 encoding (not that you need to use it here), you are correct that the "stock" Base64 character set includes 2 characters that would cause troubles if passed around in URLs. The alternative Base64 encoding called Base64url simply replaces those 2 troublesome characters with two safe characters. Namely, a "+" is replaced with a "-" and a "/" is replaced with a "_". So, plus to minus, and the forward slash "lies down" to become an underscore. There are a lot of places where base64url encoding / decoding are already available. – Frugal Guy Sep 22 '22 at 17:12
  • 1
    If your token is simply the hex representation of 32 random bytes, I would not bother with double encoding. Remember: those Hex characters are already an encoding of the binary data. So, if you *do* perform some Base64 encoding, then if what you stored server-side was the 32 random binary bytes, you'll have to: a) base64 decode which will give you binary data, then b) reconstruct the hex character string from the binary data, then c) decode the hex string to the original 32 binary bytes. All to no purpose. Just send the hex string in the URL. It will be fine. – Frugal Guy Sep 22 '22 at 17:17

4 Answers4

14

You don't need a third-party library for that. You can just use base64url encoding (starting from nodejs v14.18.0)

const encoded_token = Buffer.from(token).toString('base64url');
Ihor Sakailiuk
  • 5,642
  • 3
  • 21
  • 35
7

I solved it using URLSafeBase64 nodejs LIB at https://www.npmjs.org/package/urlsafe-base64

var email =email_lines.join("\r\n").trim();
var base64EncodedEmail = URLSafeBase64.encode(new Buffer(email));
gmail.users.messages.send({userId:"me",
        resource: {raw:base64EncodedEmail} }, callbackFn});
peterh
  • 11,875
  • 18
  • 85
  • 108
Luis Loaiza
  • 71
  • 1
  • 2
0

Another option is base64url library:

base64url("ladies and gentlemen we are floating in space");
// bGFkaWVzIGFuZCBnZW50bGVtZW4gd2UgYXJlIGZsb2F0aW5nIGluIHNwYWNl
Pavel Chuchuva
  • 22,633
  • 10
  • 99
  • 115
-2

base64 can indeed contain forward slashes, but base32 can't!

Gung Foo
  • 13,392
  • 5
  • 31
  • 39
  • Does this implicitly imply that it base64 is unsuitable for URIs (e.g. are they *invalid*)? Or does it simply that handling needs to be different? –  Sep 27 '12 at 22:46
  • 1
    look at the set of possible characters. if you do not change the available characters used for encoding, then a cell could (theoretically) equate to a value of 64, which would give you a / in your string. Change the charset for your base64 function or use base32 – Gung Foo Sep 27 '12 at 22:50
  • Thanks, do you think there is any benefit to using base32 encoded string, instead of the un-encoded token? – chovy Sep 28 '12 at 00:59
  • base32 encoded strings will take up more room than base64 ones since there is only half the characters to encode with, i see no benefit, no :) – Gung Foo Sep 28 '12 at 07:44