frasertweedale / hs-jose

Haskell JOSE and JWT library
http://hackage.haskell.org/package/jose
Apache License 2.0
122 stars 46 forks source link

Obtain unverified payload? #109

Closed torgeirsh closed 2 years ago

torgeirsh commented 2 years ago

The documentation for the JWS type says "The payload can only be accessed by verifying the JWS." For certain test scenarios it would be useful to obtain the payload/ClaimsSet without verification. Could such a function be added, possibly with "unsafe" as part of the name?

frasertweedale commented 2 years ago

Thanks for the query. But I am not going to add that to the library. If you really need it, you can decode the JSON yourself using aeson (or other JSON library) directly.

I could possibly be persuaded if you can explain in detail the scenario(s) where such an "escape hatch" would be of significant assistance. "Certain test scenarios" is much too vague, I'm afraid.

torgeirsh commented 2 years ago

I'm not sure I follow you on the JSON decoding part. The token I want to decode is a base64-like string. Do you mean implementing my own FromCompact instance? Since the library (probably rightfully) doesn't export the functionality used in its FromCompact instance for the JWS type, I would have to copy and paste the code into my application, but that might be feasible unless it depends on too much unexported functionality.

One use case is integration testing when you don't have access to the private part of the key used to verify tokens, so you can't properly sign the tokens used for testing. Ignoring the signature is far from ideal, but better than not being able to test under those circumstances.

As I type this, I realise that instead of signing the test tokens with a dummy key, it's also possible to simply not sign them. I have to add an extra dot at the end of the token, otherwise decodeCompact gives me the error "CompactDecodeError Invalid number of parts: Expected 3 parts; got 2" (is that a bug?), but verifyClaims works fine as long as I add "None" to the set of allowed algorithms in the validation settings. That might be a good enough escape hatch for now.

frasertweedale commented 2 years ago

Ah, you're using the compact representation. Well then, just split on "." and base64url-decode the second part. See https://datatracker.ietf.org/doc/html/rfc7515#section-3.1 for details. That gives you a byte string. Then you can use aeson to parse it into a ClaimsSet.

I don't think I comprehend your test scenario well enough to see what you are trying to do.

Regarding this:

I have to add an extra dot at the end of the token, otherwise decodeCompact gives me the error "CompactDecodeError Invalid number of parts: Expected 3 parts; got 2" (is that a bug?),

Can you please give as much detail as possible about how you are generating the token? Is it generated using hs-jose or another program/library?

torgeirsh commented 2 years ago

Thank you for the information on manual decoding. Regarding the unsigned token, I generated it online using https://token.dev/ by setting algorithm to none.

frasertweedale commented 2 years ago

@torgeirsh thanks. The bug is at token.dev - they should put the trailing period in the token. More accurately, the signature value of the "none" algorithm is the empty string. RFC 7515 provides an example of an unsecured JWS and the second period is indeed present: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.5.

I'm going to close this issue now.

torgeirsh commented 2 years ago

Good to know, thanks for looking into it!