frasertweedale / hs-jose

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

audience parsing as "JSON" fails if it contains a colon (:) #84

Closed ecthiender closed 4 years ago

ecthiender commented 4 years ago

The docs (https://hackage.haskell.org/package/jose-0.8.0.0/docs/Crypto-JWT.html#t:StringOrURI) says using the IsString instance with a : in a string will fail, if it's not a URI.

But is it applicable for FromJSON instance as well?

When I use the following JSON payload and try to decode it as a ClaimsSet:

{
  "aud": [
    "469a5118-2696-4740-a544-f52425350419:console"
  ],
  "auth_time": 1564485526,
  "exp": 1564489130,
  "iat": 1564485530,
  "iss": "http://example.com/",
  "jti": "ba5d56ec-af8a-4767-aba5-cda72d1c487d",
  "nonce": "",
  "rat": 1564485515,
  "sid": "9ba52187-c672-459a-8eb3-0feafdda9e4a",
  "sub": "1"
}
let jwt = "{\"aud\": [\"469a5118-2696-4740-a544-f52425350419:console\"], \"auth_time\": 1564485526, \"exp\": 1564489130, \"iat\": 1564485530, \"iss\": \"http://example.com/\", \"jti\": \"ba5d56ec-af8a-4767-aba5-cda72d1c487d\", \"nonce\": \"\", \"rat\": 1564485515, \"sid\": \"9ba52187-c672-459a-8eb3-0feafdda9e4a\", \"sub\": \"1\"}\n\n"
eitherDecode jwt :: Either String ClaimsSet

Results in:

Left "Error in $.aud: expected StringOrURI, encountered Array"

Expected

I was expecting this to parse successfully, as I am using the FromJSON instance. Am I doing something wrong?

frasertweedale commented 4 years ago

Thank you for the report. It is not a bug; this is the required behaviour. Per https://tools.ietf.org/html/rfc7519#section-4.1.3:

In the general case, the "aud" value is an array of case-
sensitive strings, each containing a StringOrURI value.  In the
special case when the JWT has one audience, the "aud" value MAY be a
single case-sensitive string containing a StringOrURI value.

and https://tools.ietf.org/html/rfc7519#section-2:

StringOrURI
   A JSON string value, with the additional requirement that while
   arbitrary string values MAY be used, any value containing a ":"
   character MUST be a URI [RFC3986].  StringOrURI values are
   compared as case-sensitive strings with no transformations or
   canonicalizations applied.

The "aud" value contains a colon, and is not a URI. Therefore it must be rejected.

ecthiender commented 4 years ago

@frasertweedale thanks for the pointer :+1: . Also do you think the error message can be improved? I'll be happy to submit a PR if you think that's the case.

frasertweedale commented 4 years ago

@ecthiender yeah the message can probably be improved; it will have to be done in the instance FromJSON Audience because of the silly "if there's only one it can be just the string" special case.