packages feed

jose 0.8.4 → 0.8.4.1

raw patch · 14 files changed

+44/−79 lines, 14 filesdep ~QuickCheckdep ~aesondep ~base64-bytestringPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: QuickCheck, aeson, base64-bytestring

API changes (from Hackage documentation)

- Crypto.JOSE.Error: _AlgorithmMismatch :: AsError r_amUc => Prism' r_amUc String
+ Crypto.JOSE.Error: _AlgorithmMismatch :: AsError r_aepM => Prism' r_aepM String
- Crypto.JOSE.Error: _AlgorithmNotImplemented :: AsError r_amUc => Prism' r_amUc ()
+ Crypto.JOSE.Error: _AlgorithmNotImplemented :: AsError r_aepM => Prism' r_aepM ()
- Crypto.JOSE.Error: _CompactDecodeError :: AsError r_amUc => Prism' r_amUc CompactDecodeError
+ Crypto.JOSE.Error: _CompactDecodeError :: AsError r_aepM => Prism' r_aepM CompactDecodeError
- Crypto.JOSE.Error: _CryptoError :: AsError r_amUc => Prism' r_amUc CryptoError
+ Crypto.JOSE.Error: _CryptoError :: AsError r_aepM => Prism' r_aepM CryptoError
- Crypto.JOSE.Error: _Error :: AsError r_amUc => Prism' r_amUc Error
+ Crypto.JOSE.Error: _Error :: AsError r_aepM => Prism' r_aepM Error
- Crypto.JOSE.Error: _JSONDecodeError :: AsError r_amUc => Prism' r_amUc String
+ Crypto.JOSE.Error: _JSONDecodeError :: AsError r_aepM => Prism' r_aepM String
- Crypto.JOSE.Error: _JWSCritUnprotected :: AsError r_amUc => Prism' r_amUc ()
+ Crypto.JOSE.Error: _JWSCritUnprotected :: AsError r_aepM => Prism' r_aepM ()
- Crypto.JOSE.Error: _JWSInvalidSignature :: AsError r_amUc => Prism' r_amUc ()
+ Crypto.JOSE.Error: _JWSInvalidSignature :: AsError r_aepM => Prism' r_aepM ()
- Crypto.JOSE.Error: _JWSNoSignatures :: AsError r_amUc => Prism' r_amUc ()
+ Crypto.JOSE.Error: _JWSNoSignatures :: AsError r_aepM => Prism' r_aepM ()
- Crypto.JOSE.Error: _JWSNoValidSignatures :: AsError r_amUc => Prism' r_amUc ()
+ Crypto.JOSE.Error: _JWSNoValidSignatures :: AsError r_aepM => Prism' r_aepM ()
- Crypto.JOSE.Error: _KeyMismatch :: AsError r_amUc => Prism' r_amUc Text
+ Crypto.JOSE.Error: _KeyMismatch :: AsError r_aepM => Prism' r_aepM Text
- Crypto.JOSE.Error: _KeySizeTooSmall :: AsError r_amUc => Prism' r_amUc ()
+ Crypto.JOSE.Error: _KeySizeTooSmall :: AsError r_aepM => Prism' r_aepM ()
- Crypto.JOSE.Error: _NoUsableKeys :: AsError r_amUc => Prism' r_amUc ()
+ Crypto.JOSE.Error: _NoUsableKeys :: AsError r_aepM => Prism' r_aepM ()
- Crypto.JOSE.Error: _OtherPrimesNotSupported :: AsError r_amUc => Prism' r_amUc ()
+ Crypto.JOSE.Error: _OtherPrimesNotSupported :: AsError r_aepM => Prism' r_aepM ()
- Crypto.JOSE.Error: _RSAError :: AsError r_amUc => Prism' r_amUc Error
+ Crypto.JOSE.Error: _RSAError :: AsError r_aepM => Prism' r_aepM Error
- Crypto.JOSE.Error: class AsError r_amUc
+ Crypto.JOSE.Error: class AsError r_aepM
- Crypto.JWT: _JWSError :: AsJWTError r_a1fhJ => Prism' r_a1fhJ Error
+ Crypto.JWT: _JWSError :: AsJWTError r_a12w1 => Prism' r_a12w1 Error
- Crypto.JWT: _JWTClaimsSetDecodeError :: AsJWTError r_a1fhJ => Prism' r_a1fhJ String
+ Crypto.JWT: _JWTClaimsSetDecodeError :: AsJWTError r_a12w1 => Prism' r_a12w1 String
- Crypto.JWT: _JWTError :: AsJWTError r_a1fhJ => Prism' r_a1fhJ JWTError
+ Crypto.JWT: _JWTError :: AsJWTError r_a12w1 => Prism' r_a12w1 JWTError
- Crypto.JWT: _JWTExpired :: AsJWTError r_a1fhJ => Prism' r_a1fhJ ()
+ Crypto.JWT: _JWTExpired :: AsJWTError r_a12w1 => Prism' r_a12w1 ()
- Crypto.JWT: _JWTIssuedAtFuture :: AsJWTError r_a1fhJ => Prism' r_a1fhJ ()
+ Crypto.JWT: _JWTIssuedAtFuture :: AsJWTError r_a12w1 => Prism' r_a12w1 ()
- Crypto.JWT: _JWTNotInAudience :: AsJWTError r_a1fhJ => Prism' r_a1fhJ ()
+ Crypto.JWT: _JWTNotInAudience :: AsJWTError r_a12w1 => Prism' r_a12w1 ()
- Crypto.JWT: _JWTNotInIssuer :: AsJWTError r_a1fhJ => Prism' r_a1fhJ ()
+ Crypto.JWT: _JWTNotInIssuer :: AsJWTError r_a12w1 => Prism' r_a12w1 ()
- Crypto.JWT: _JWTNotYetValid :: AsJWTError r_a1fhJ => Prism' r_a1fhJ ()
+ Crypto.JWT: _JWTNotYetValid :: AsJWTError r_a12w1 => Prism' r_a12w1 ()
- Crypto.JWT: class AsJWTError r_a1fhJ
+ Crypto.JWT: class AsJWTError r_a12w1
- Crypto.JWT: class HasJWTValidationSettings c_a1g2x
+ Crypto.JWT: class HasJWTValidationSettings c_a13eH
- Crypto.JWT: jWTValidationSettings :: HasJWTValidationSettings c_a1g2x => Lens' c_a1g2x JWTValidationSettings
+ Crypto.JWT: jWTValidationSettings :: HasJWTValidationSettings c_a13eH => Lens' c_a13eH JWTValidationSettings
- Crypto.JWT: jwtValidationSettingsAllowedSkew :: HasJWTValidationSettings c_a1g2x => Lens' c_a1g2x NominalDiffTime
+ Crypto.JWT: jwtValidationSettingsAllowedSkew :: HasJWTValidationSettings c_a13eH => Lens' c_a13eH NominalDiffTime
- Crypto.JWT: jwtValidationSettingsAudiencePredicate :: HasJWTValidationSettings c_a1g2x => Lens' c_a1g2x (StringOrURI -> Bool)
+ Crypto.JWT: jwtValidationSettingsAudiencePredicate :: HasJWTValidationSettings c_a13eH => Lens' c_a13eH (StringOrURI -> Bool)
- Crypto.JWT: jwtValidationSettingsCheckIssuedAt :: HasJWTValidationSettings c_a1g2x => Lens' c_a1g2x Bool
+ Crypto.JWT: jwtValidationSettingsCheckIssuedAt :: HasJWTValidationSettings c_a13eH => Lens' c_a13eH Bool
- Crypto.JWT: jwtValidationSettingsIssuerPredicate :: HasJWTValidationSettings c_a1g2x => Lens' c_a1g2x (StringOrURI -> Bool)
+ Crypto.JWT: jwtValidationSettingsIssuerPredicate :: HasJWTValidationSettings c_a13eH => Lens' c_a13eH (StringOrURI -> Bool)
- Crypto.JWT: jwtValidationSettingsValidationSettings :: HasJWTValidationSettings c_a1g2x => Lens' c_a1g2x ValidationSettings
+ Crypto.JWT: jwtValidationSettingsValidationSettings :: HasJWTValidationSettings c_a13eH => Lens' c_a13eH ValidationSettings

Files

example/Main.hs view
@@ -1,5 +1,4 @@ {-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}-{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-}  import Data.Maybe (fromJust)@@ -29,9 +28,7 @@     "jws-verify" -> doJwsVerify (tail args)     "jwt-sign" -> doJwtSign (tail args)     "jwt-verify" -> doJwtVerify (tail args)-#if MIN_VERSION_aeson(0,10,0)     "jwk-thumbprint" -> doThumbprint (tail args)-#endif  doGen :: [String] -> IO () doGen [kty] = do@@ -40,14 +37,10 @@                   "rsa" -> RSAGenParam 256                   "ec" -> ECGenParam P_256                   "eddsa" -> OKPGenParam Ed25519-#if MIN_VERSION_aeson(0,10,0)   let     h = view thumbprint k :: Digest SHA256     kid' = view (re (base64url . digest) . utf8) h     k' = set jwkKid (Just kid') k-#else-  let k' = k-#endif   L.putStr (encode k')  -- | Mint a JWT.  Args are:@@ -102,7 +95,6 @@ rightOrDie s = either (die . (\e -> s <> ": " <> show e)) pure  -#if MIN_VERSION_aeson(0,10,0) -- | Print a base64url-encoded SHA-256 JWK Thumbprint.  Args are: -- -- 1. filename of JWK@@ -112,4 +104,3 @@   Just k <- decode <$> L.readFile jwkFilename   let h = view thumbprint k :: Digest SHA256   L.putStr $ review (base64url . digest) h-#endif
jose.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                jose-version:             0.8.4+version:             0.8.4.1 synopsis:   Javascript Object Signing and Encryption and JSON Web Token library description:@@ -12,7 +12,7 @@   .   EdDSA signatures (RFC 8037) are supported (Ed25519 only).   .-  JWK Thumbprint (RFC 7638) is supported (requires /aeson/ >= 0.10).+  JWK Thumbprint (RFC 7638) is supported.   .   JSON Web Encryption (JWE; RFC 7516) is not yet implemented.   .@@ -31,7 +31,7 @@ category:            Cryptography build-type:          Simple tested-with:-  GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.4, GHC==8.10.2+  GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.4, GHC==8.10.4, GHC==9.0.1  flag demos   description: Build demonstration programs@@ -43,7 +43,7 @@    build-depends:     base >= 4.8 && < 5-    , aeson >= 0.8.0.1+    , aeson >= 0.11.1.0     , bytestring == 0.10.*     , lens >= 4.16     , mtl >= 2@@ -79,7 +79,7 @@    build-depends:     attoparsec-    , base64-bytestring >= 1.1 && < 1.3+    , base64-bytestring >= 1.2.1.0 && < 1.3     , concise >= 0.1     , containers >= 0.5     , cryptonite >= 0.7@@ -90,7 +90,7 @@     , unordered-containers == 0.2.*     , time >= 1.5     , network-uri >= 2.6-    , QuickCheck >= 2+    , QuickCheck >= 2.9     , quickcheck-instances     , x509 >= 1.4     , vector@@ -141,7 +141,7 @@     , tasty-hspec >= 1.0     , tasty-quickcheck     , hspec-    , QuickCheck+    , QuickCheck >= 2.9     , quickcheck-instances  executable jose-example
src/Crypto/JOSE/Compact.hs view
@@ -48,4 +48,4 @@ -- | Encode data to a compact representation. -- encodeCompact :: (ToCompact a) => a -> L.ByteString-encodeCompact = (L.intercalate ".") . toCompact+encodeCompact = L.intercalate "." . toCompact
src/Crypto/JOSE/Header.hs view
@@ -169,10 +169,12 @@ -- | Lens for the 'Protection' of a 'HeaderParam' protection :: Lens' (HeaderParam p a) p protection f (HeaderParam p v) = fmap (\p' -> HeaderParam p' v) (f p)+{-# ANN protection "HLint: ignore Avoid lambda using `infix`" #-}  -- | Lens for a 'HeaderParam' value param :: Lens' (HeaderParam p a) a param f (HeaderParam p v) = fmap (\v' -> HeaderParam p v') (f v)+{-# ANN param "HLint: ignore Avoid lambda" #-}  -- | Getter for whether a parameter is protected isProtected :: (ProtectionIndicator p) => Getter (HeaderParam p a) Bool
src/Crypto/JOSE/JWA/JWK.hs view
@@ -77,7 +77,7 @@ import Control.Monad.Except (MonadError) import Data.Bifunctor import Data.Foldable (toList)-import Data.Maybe (fromMaybe, isJust)+import Data.Maybe (isJust) import Data.Monoid ((<>))  import Control.Lens hiding ((.=), elements)@@ -444,7 +444,7 @@     RSA.PrivateKey (RSA.PublicKey (Types.intBytes n) n e) d       (opt' rsaP) (opt' rsaQ) (opt' rsaDp) (opt' rsaDq) (opt' rsaQi)     where-      opt' f = fromMaybe 0 (unB64I . f <$> opt)+      opt' f = maybe 0 (unB64I . f) opt       unB64I (Types.Base64Integer x) = x rsaPrivateKey _ = throwing _KeyMismatch "not an RSA private key" @@ -710,9 +710,8 @@     X25519Key pk _  -> Just (X25519Key pk Nothing)  instance AsPublicKey KeyMaterial where-  asPublicKey = to (\x -> case x of+  asPublicKey = to $ \case     OctKeyMaterial _  -> Nothing     RSAKeyMaterial k  -> RSAKeyMaterial  <$> view asPublicKey k     ECKeyMaterial k   -> ECKeyMaterial   <$> view asPublicKey k     OKPKeyMaterial k  -> OKPKeyMaterial  <$> view asPublicKey k-    )
src/Crypto/JOSE/JWE.hs view
@@ -96,8 +96,8 @@     <*> headerOptional "jwk" hp hu     <*> headerOptional "kid" hp hu     <*> headerOptional "x5u" hp hu-    <*> ((fmap . fmap . fmap . fmap)-          (\(Types.Base64X509 cert) -> cert) (headerOptional "x5c" hp hu))+    <*> (fmap . fmap . fmap . fmap)+          (\(Types.Base64X509 cert) -> cert) (headerOptional "x5c" hp hu)     <*> headerOptional "x5t" hp hu     <*> headerOptional "x5t#S256" hp hu     <*> headerOptional "typ" hp hu@@ -145,7 +145,7 @@ -- parseParamsFor :: HasParams b => Proxy b -> Maybe Object -> Maybe Object -> Parser a  data JWE a p = JWE-  { _protectedRaw :: (Maybe T.Text)      -- ^ Encoded protected header, if available+  { _protectedRaw :: Maybe T.Text       -- ^ Encoded protected header, if available   , _jweIv :: Maybe Types.Base64Octets  -- ^ JWE Initialization Vector   , _jweAad :: Maybe Types.Base64Octets -- ^ JWE AAD   , _jweCiphertext :: Types.Base64Octets  -- ^ JWE Ciphertext
src/Crypto/JOSE/JWK.hs view
@@ -12,7 +12,6 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE OverloadedStrings #-}@@ -72,13 +71,11 @@   , fromOctets   , fromX509Certificate -#if MIN_VERSION_aeson(0,10,0)   -- * JWK Thumbprint   , thumbprint   , digest   , Types.base64url   , module Crypto.Hash-#endif    -- * JWK Set   , JWKSet(..)@@ -336,7 +333,6 @@   OKPKeyMaterial _ -> throwing _KeyMismatch "Cannot sign with OKP ECDH key"  -#if MIN_VERSION_aeson(0,10,0) -- | Compute the JWK Thumbprint of a JWK -- thumbprint :: HashAlgorithm a => Getter JWK (Digest a)@@ -369,4 +365,3 @@     b64 = Types.Base64Octets . BA.convert     okpSeries crv pk =       "crv" .= (crv :: T.Text) <> "kty" .= ("OKP" :: T.Text) <> "x" .= b64 pk-#endif
src/Crypto/JOSE/JWS.hs view
@@ -236,7 +236,7 @@ -- | Construct a minimal header with the given algorithm and -- protection indicator for the /alg/ header. ---newJWSHeader :: (p, Alg) -> (JWSHeader p)+newJWSHeader :: (p, Alg) -> JWSHeader p newJWSHeader a = JWSHeader (uncurry HeaderParam a) z z z z z z z z z z   where z = Nothing @@ -323,7 +323,7 @@         Nothing -> id         Just o -> ("header" .= o :)     in-      object $ (pro . unp) [("signature" .= sig)]+      object $ (pro . unp) ["signature" .= sig]   instance HasParams JWSHeader where@@ -333,8 +333,8 @@     <*> headerOptional "jwk" hp hu     <*> headerOptional "kid" hp hu     <*> headerOptional "x5u" hp hu-    <*> ((fmap . fmap . fmap . fmap)-          (\(Types.Base64X509 cert) -> cert) (headerOptional "x5c" hp hu))+    <*> (fmap . fmap . fmap . fmap)+          (\(Types.Base64X509 cert) -> cert) (headerOptional "x5c" hp hu)     <*> headerOptional "x5t" hp hu     <*> headerOptional "x5t#S256" hp hu     <*> headerOptional "typ" hp hu@@ -344,7 +344,7 @@         (fromMaybe mempty hp <> fromMaybe mempty hu))   params h =     catMaybes-      [ Just (view (alg . isProtected) h, "alg" .= (view (alg . param) h))+      [ Just (view (alg . isProtected) h, "alg" .= view (alg . param) h)       , fmap (\p -> (view isProtected p, "jku" .= view param p)) (view jku h)       , fmap (\p -> (view isProtected p, "jwk" .= view param p)) (view jwk h)       , fmap (\p -> (view isProtected p, "kid" .= view param p)) (view kid h)@@ -486,7 +486,7 @@      , ProtectionIndicator p      )   => s          -- ^ Payload-  -> t ((a p), JWK) -- ^ Traversable of header, key pairs+  -> t (a p, JWK) -- ^ Traversable of header, key pairs   -> m (JWS t p a) signJWS s =   let s' = view recons s@@ -533,12 +533,12 @@   validationSettingsAlgorithms :: Lens' a (S.Set Alg)   validationSettingsAlgorithms = validationSettings . go where     go f (ValidationSettings algs pol) =-      (\algs' -> ValidationSettings algs' pol) <$> f algs+      (`ValidationSettings` pol) <$> f algs    validationSettingsValidationPolicy :: Lens' a ValidationPolicy   validationSettingsValidationPolicy = validationSettings . go where     go f (ValidationSettings algs pol) =-      (\pol' -> ValidationSettings algs pol') <$> f pol+      ValidationSettings algs <$> f pol  instance HasValidationSettings ValidationSettings where   validationSettings = id
src/Crypto/JOSE/Types.hs view
@@ -96,8 +96,8 @@     go :: Integer -> Integer -> Gen Integer     go 0 n = pure n     go k n =-      (n * 256 +) . fromIntegral <$> (arbitraryBoundedIntegral :: Gen Word8)-      >>= go (k - 1)+      (arbitraryBoundedIntegral :: Gen Word8)+      >>= go (k - 1) . (n * 256 +) . fromIntegral   instance Arbitrary Base64Integer where
src/Crypto/JOSE/Types/Orphans.hs view
@@ -12,44 +12,18 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -{-# LANGUAGE CPP #-} {-# OPTIONS_GHC -fno-warn-orphans #-}  module Crypto.JOSE.Types.Orphans where -import Data.List.NonEmpty (NonEmpty(..))+import Data.Aeson import qualified Data.Text as T import Network.URI (URI, parseURI)-import Test.QuickCheck -#if ! MIN_VERSION_aeson(0,11,1)-import Data.Foldable (toList)-import qualified Data.Vector as V-#endif -import Data.Aeson---#if ! MIN_VERSION_aeson(0,11,1)-instance FromJSON a => FromJSON (NonEmpty a) where-  parseJSON = withArray "NonEmpty [a]" $ \v -> case toList v of-    [] -> fail "Non-empty list required"-    (x:xs) -> mapM parseJSON (x :| xs)--instance ToJSON a => ToJSON (NonEmpty a) where-  toJSON = Array . V.fromList . map toJSON . toList-#endif-- instance FromJSON URI where   parseJSON = withText "URI" $     maybe (fail "not a URI") return . parseURI . T.unpack  instance ToJSON URI where   toJSON = String . T.pack . show---#if ! MIN_VERSION_QuickCheck(2,9,0)-instance Arbitrary a => Arbitrary (NonEmpty a) where-  arbitrary = (:|) <$> arbitrary <*> arbitrary-#endif
src/Crypto/JWT.hs view
@@ -130,7 +130,7 @@ import Control.Lens.Cons.Extras (recons) import Control.Monad.Error.Lens (throwing, throwing_) import Control.Monad.Except (MonadError)-import Control.Monad.Reader (ReaderT, ask, runReaderT)+import Control.Monad.Reader (ReaderT, asks, runReaderT) import Data.Aeson import qualified Data.HashMap.Strict as M import qualified Data.Text as T@@ -436,14 +436,13 @@   -> ClaimsSet   -> m ClaimsSet validateClaimsSet conf claims =-  traverse_ (($ claims) . ($ conf))+  claims <$ traverse_ (($ claims) . ($ conf))     [ validateExpClaim     , validateIatClaim     , validateNbfClaim     , validateIssClaim     , validateAudClaim     ]-  *> pure claims  validateExpClaim   :: (MonadTime m, HasAllowedSkew a, AsJWTError e, MonadError e m)@@ -511,7 +510,7 @@ newtype WrappedUTCTime = WrappedUTCTime { getUTCTime :: UTCTime }  instance Monad m => MonadTime (ReaderT WrappedUTCTime m) where-  currentTime = getUTCTime <$> ask+  currentTime = asks getUTCTime   -- | Cryptographically verify a JWS JWT, then validate the
test/JWK.hs view
@@ -12,7 +12,6 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-}  module JWK where@@ -41,9 +40,7 @@   jwkAppendixC1Spec   jwsAppendixA1Spec   cfrgSpec-#if MIN_VERSION_aeson(0,10,0)   thumbprintSpec-#endif  jwsAppendixA1Spec :: Spec jwsAppendixA1Spec = describe "RFC 7515 A.1.1.  JWK" $ do@@ -307,7 +304,6 @@   <> "\"x\":\"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo\"}"  -#if MIN_VERSION_aeson(0,10,0) thumbprintSpec :: Spec thumbprintSpec = describe "JWK Thumbprint" $ do   describe "RFC 7638 §3.1.  Example JWK Thumbprint Computation" $ do@@ -333,4 +329,3 @@     it "correctly computes thumbprint of Ed25519 key" $       review (base64url . digest) (view thumbprint k :: Digest SHA256)         `shouldBe` ("kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k" :: B.ByteString)-#endif
test/JWT.hs view
@@ -23,6 +23,8 @@  import Control.Lens import Control.Lens.Extras (is)+import Control.Monad.Except (runExceptT)+import Control.Monad.Trans (liftIO) import Control.Monad.Reader (MonadReader(..), ReaderT, runReaderT) import Control.Monad.State (execState) import Control.Monad.Time (MonadTime(..))@@ -70,6 +72,14 @@           <> "\"http://example.com/is_root\":true}"       in         decode claimsJSON `shouldBe` Just exampleClaimsSet++    it "JWT compact round-trip" $ do+      jwk <- genJWK $ RSAGenParam 256+      res <- runExceptT $ do+        token <- signClaims jwk (newJWSHeader ((), RS512)) emptyClaimsSet+        token' <- decodeCompact . encodeCompact $ token+        liftIO $ token' `shouldBe` token+      either (error . show) return (res :: Either JWTError ()) :: IO ()      it "formats to a parsable and equal value" $       decode (encode exampleClaimsSet) `shouldBe` Just exampleClaimsSet
test/Properties.hs view
@@ -34,14 +34,14 @@  properties = testGroup "Properties"   [ testProperty "SizedBase64Integer round-trip"-    (prop_roundTrip :: SizedBase64Integer -> Bool)-  , testProperty "JWK round-trip" (prop_roundTrip :: JWK -> Bool)+    (prop_roundTrip :: SizedBase64Integer -> Property)+  , testProperty "JWK round-trip" (prop_roundTrip :: JWK -> Property)   , testProperty "RSA gen, sign and verify" prop_rsaSignAndVerify   , testProperty "gen, sign with best alg, verify" prop_bestJWSAlg   ] -prop_roundTrip :: (Eq a, ToJSON a, FromJSON a) => a -> Bool-prop_roundTrip a = decode (encode [a]) == Just [a]+prop_roundTrip :: (Eq a, Show a, ToJSON a, FromJSON a) => a -> Property+prop_roundTrip a = decode (encode [a]) === Just [a]  debugRoundTrip   :: (Show a, Arbitrary a, ToJSON a, FromJSON a)