auth0 / node-jws

JSON Web Signatures
http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html
MIT License
711 stars 108 forks source link

Need to specify encoding on decode. #72

Open plfx opened 7 years ago

plfx commented 7 years ago

My JWS payload is some raw bytes, which I pass to the encode function as base64, using the supported "base64" encoding option:

jws.sign({
  header: {
    alg: "HS256"
  },
  payload: "myPayloadBase64=",
  secret: "secret",
  encoding: "base64"
})
// 'eyJhbGciOiJIUzI1NiJ9.myPayloadBase64.rFU9W9o-1Mw3jEudDOFjQZHrxOOmMZdTRnLbXTL2VY8'

When I decode this, there's no corresponding option to decode directly to base64. Decode gives me a string using the encoded bytes, but it contains some escaped character values and is not compatible with Buffer:

const decodedPayload = jws.decode('eyJhbGciOiJIUzI1NiJ9.myPayloadBase64.rFU9W9o-1Mw3jEudDOFjQZHrxOOmMZdTRnLbXTL2VY8')
// '�#��Z\u001at\u0016�{�'

Buffer.from(decodedPayload, "utf8").toString("base64")
//'77+9I++/ve+/vVoadBbvv71777+9'
// should be 'myPayloadBase64='

My workaround right now is to not use decode at all. Instead, I just split('.')[1] and then require('base64-url') to decode the bytes or convert it to normal base64.

It would be much easier if I were able to pass the encoding I used to the decode method to get my base64 (or whatever other encoding) directly.

jws.decode(jwsStr, "base64" /* any supported encoding */)
/*
  {
    header: { alg: "HS256" },
    payload: "myPayloadBase64=",
    signature: "rFU9W9o-1Mw3jEudDOFjQZHrxOOmMZdTRnLbXTL2VY8"
  }
*/

As an additional feature suggestion, this would also let people ask decode to automatically parse JSON payloads:

const encoded = jws.sign({header:{alg: "HS256"}, payload: {test: "value"}, secret: "secret"})
jws.decode(encoded, "json")
// {test: 'value'}
novemberborn commented 6 years ago

The problem is that the payload is decoded to a string, rather than a buffer. Looking at the VerifyStream implementation I think encoding support is fundamentally broken. It should probably be removed entirely, returning the raw payload bytes. I suppose for typ: 'JWT' it could still parse the payload as if it was a JSON-encoded object.