Description
If you pass an object as the payload to sign
, it eventually gets serialized to a string by calling JSON.stringify
, here: https://github.com/brianloveswords/node-jws/blob/master/lib/tostring.js#L9
The output order of JSON.stringify is not guaranteed. For example, one implementation may serialize {one: 'two', three: 'four'}
as '{"one":"two","three":"four"}'
and another may serialize it as '{"three":"four","one":"two"}'
. The former would create a different MAC than the latter.
The latest ECMA spec for JSON.stringify says that it should produce the same order as Object.keys, which should produce the same order as for ... in
, which uses Object.[[Enumerate]]()
to enumerate object keys. [[Enumerate]]
is a) deprecated, and b) the specification contains this note:
The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.
It might be fine if all you are doing is verifying that a generated signature is valid for the provided payload, and the verification operates on a provided string. But it would be confusing if signing the same payload generated different signatures on different Node versions, or if I generate two different JWT's using the same payload and secret key and, say, HMAC-SHA256, and expect the signatures to be equal.
In any event, you may want to provide a large warning saying that the key ordering isn't deterministic, and you may generate different signatures for the same payload and secret key pair.