packages feed

jose 0.5.0.1 → 0.5.0.2

raw patch · 3 files changed

+111/−5 lines, 3 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Crypto.JWT: JWTIssuedAtFuture :: JWTError
+ Crypto.JWT: JWTJWS :: (JWS JWSHeader) -> JWTCrypto
+ Crypto.JWT: JWTNotInIssuer :: JWTError
+ Crypto.JWT: _JWTIssuedAtFuture :: AsJWTError r_a1KYm => Prism' r_a1KYm ()
+ Crypto.JWT: _JWTNotInIssuer :: AsJWTError r_a1KYm => Prism' r_a1KYm ()
+ Crypto.JWT: checkIssuedAt :: HasCheckIssuedAt s => Lens' s Bool
+ Crypto.JWT: class HasCheckIssuedAt s
+ Crypto.JWT: class HasIssuerPredicate s
+ Crypto.JWT: data JWTCrypto
+ Crypto.JWT: instance Crypto.JWT.HasJWTValidationSettings a => Crypto.JWT.HasCheckIssuedAt a
+ Crypto.JWT: instance Crypto.JWT.HasJWTValidationSettings a => Crypto.JWT.HasIssuerPredicate a
+ Crypto.JWT: issuerPredicate :: HasIssuerPredicate s => Lens' s (StringOrURI -> Bool)
+ Crypto.JWT: jwtValidationSettingsCheckIssuedAt :: HasJWTValidationSettings c_a1LAX => Lens' c_a1LAX Bool
+ Crypto.JWT: jwtValidationSettingsIssuerPredicate :: HasJWTValidationSettings c_a1LAX => Lens' c_a1LAX (StringOrURI -> Bool)
- Crypto.JOSE.Error: _AlgorithmMismatch :: AsError r_aAzM => Prism' r_aAzM String
+ Crypto.JOSE.Error: _AlgorithmMismatch :: AsError r_aB18 => Prism' r_aB18 String
- Crypto.JOSE.Error: _AlgorithmNotImplemented :: AsError r_aAzM => Prism' r_aAzM ()
+ Crypto.JOSE.Error: _AlgorithmNotImplemented :: AsError r_aB18 => Prism' r_aB18 ()
- Crypto.JOSE.Error: _CompactDecodeError :: AsError r_aAzM => Prism' r_aAzM String
+ Crypto.JOSE.Error: _CompactDecodeError :: AsError r_aB18 => Prism' r_aB18 String
- Crypto.JOSE.Error: _CompactEncodeError :: AsError r_aAzM => Prism' r_aAzM String
+ Crypto.JOSE.Error: _CompactEncodeError :: AsError r_aB18 => Prism' r_aB18 String
- Crypto.JOSE.Error: _CryptoError :: AsError r_aAzM => Prism' r_aAzM CryptoError
+ Crypto.JOSE.Error: _CryptoError :: AsError r_aB18 => Prism' r_aB18 CryptoError
- Crypto.JOSE.Error: _Error :: AsError r_aAzM => Prism' r_aAzM Error
+ Crypto.JOSE.Error: _Error :: AsError r_aB18 => Prism' r_aB18 Error
- Crypto.JOSE.Error: _JSONDecodeError :: AsError r_aAzM => Prism' r_aAzM String
+ Crypto.JOSE.Error: _JSONDecodeError :: AsError r_aB18 => Prism' r_aB18 String
- Crypto.JOSE.Error: _JWSCritUnprotected :: AsError r_aAzM => Prism' r_aAzM ()
+ Crypto.JOSE.Error: _JWSCritUnprotected :: AsError r_aB18 => Prism' r_aB18 ()
- Crypto.JOSE.Error: _JWSInvalidSignature :: AsError r_aAzM => Prism' r_aAzM ()
+ Crypto.JOSE.Error: _JWSInvalidSignature :: AsError r_aB18 => Prism' r_aB18 ()
- Crypto.JOSE.Error: _JWSNoSignatures :: AsError r_aAzM => Prism' r_aAzM ()
+ Crypto.JOSE.Error: _JWSNoSignatures :: AsError r_aB18 => Prism' r_aB18 ()
- Crypto.JOSE.Error: _JWSNoValidSignatures :: AsError r_aAzM => Prism' r_aAzM ()
+ Crypto.JOSE.Error: _JWSNoValidSignatures :: AsError r_aB18 => Prism' r_aB18 ()
- Crypto.JOSE.Error: _KeyMismatch :: AsError r_aAzM => Prism' r_aAzM String
+ Crypto.JOSE.Error: _KeyMismatch :: AsError r_aB18 => Prism' r_aB18 String
- Crypto.JOSE.Error: _KeySizeTooSmall :: AsError r_aAzM => Prism' r_aAzM ()
+ Crypto.JOSE.Error: _KeySizeTooSmall :: AsError r_aB18 => Prism' r_aB18 ()
- Crypto.JOSE.Error: _OtherPrimesNotSupported :: AsError r_aAzM => Prism' r_aAzM ()
+ Crypto.JOSE.Error: _OtherPrimesNotSupported :: AsError r_aB18 => Prism' r_aB18 ()
- Crypto.JOSE.Error: _RSAError :: AsError r_aAzM => Prism' r_aAzM Error
+ Crypto.JOSE.Error: _RSAError :: AsError r_aB18 => Prism' r_aB18 Error
- Crypto.JOSE.Error: class AsError r_aAzM where _AlgorithmNotImplemented = (.) _Error _AlgorithmNotImplemented _AlgorithmMismatch = (.) _Error _AlgorithmMismatch _KeyMismatch = (.) _Error _KeyMismatch _KeySizeTooSmall = (.) _Error _KeySizeTooSmall _OtherPrimesNotSupported = (.) _Error _OtherPrimesNotSupported _RSAError = (.) _Error _RSAError _CryptoError = (.) _Error _CryptoError _CompactEncodeError = (.) _Error _CompactEncodeError _CompactDecodeError = (.) _Error _CompactDecodeError _JSONDecodeError = (.) _Error _JSONDecodeError _JWSCritUnprotected = (.) _Error _JWSCritUnprotected _JWSNoValidSignatures = (.) _Error _JWSNoValidSignatures _JWSInvalidSignature = (.) _Error _JWSInvalidSignature _JWSNoSignatures = (.) _Error _JWSNoSignatures
+ Crypto.JOSE.Error: class AsError r_aB18 where _AlgorithmNotImplemented = (.) _Error _AlgorithmNotImplemented _AlgorithmMismatch = (.) _Error _AlgorithmMismatch _KeyMismatch = (.) _Error _KeyMismatch _KeySizeTooSmall = (.) _Error _KeySizeTooSmall _OtherPrimesNotSupported = (.) _Error _OtherPrimesNotSupported _RSAError = (.) _Error _RSAError _CryptoError = (.) _Error _CryptoError _CompactEncodeError = (.) _Error _CompactEncodeError _CompactDecodeError = (.) _Error _CompactDecodeError _JSONDecodeError = (.) _Error _JSONDecodeError _JWSCritUnprotected = (.) _Error _JWSCritUnprotected _JWSNoValidSignatures = (.) _Error _JWSNoValidSignatures _JWSInvalidSignature = (.) _Error _JWSInvalidSignature _JWSNoSignatures = (.) _Error _JWSNoSignatures
- Crypto.JOSE.JWS: class HasJWSHeader c_a1gsn where jwsHeaderAlg = (.) jWSHeader jwsHeaderAlg jwsHeaderCrit = (.) jWSHeader jwsHeaderCrit jwsHeaderCty = (.) jWSHeader jwsHeaderCty jwsHeaderJku = (.) jWSHeader jwsHeaderJku jwsHeaderJwk = (.) jWSHeader jwsHeaderJwk jwsHeaderKid = (.) jWSHeader jwsHeaderKid jwsHeaderTyp = (.) jWSHeader jwsHeaderTyp jwsHeaderX5c = (.) jWSHeader jwsHeaderX5c jwsHeaderX5t = (.) jWSHeader jwsHeaderX5t jwsHeaderX5tS256 = (.) jWSHeader jwsHeaderX5tS256 jwsHeaderX5u = (.) jWSHeader jwsHeaderX5u
+ Crypto.JOSE.JWS: class HasJWSHeader c_a1gTJ where jwsHeaderAlg = (.) jWSHeader jwsHeaderAlg jwsHeaderCrit = (.) jWSHeader jwsHeaderCrit jwsHeaderCty = (.) jWSHeader jwsHeaderCty jwsHeaderJku = (.) jWSHeader jwsHeaderJku jwsHeaderJwk = (.) jWSHeader jwsHeaderJwk jwsHeaderKid = (.) jWSHeader jwsHeaderKid jwsHeaderTyp = (.) jWSHeader jwsHeaderTyp jwsHeaderX5c = (.) jWSHeader jwsHeaderX5c jwsHeaderX5t = (.) jWSHeader jwsHeaderX5t jwsHeaderX5tS256 = (.) jWSHeader jwsHeaderX5tS256 jwsHeaderX5u = (.) jWSHeader jwsHeaderX5u
- Crypto.JOSE.JWS: class HasValidationSettings c_a1hnP where validationSettingsAlgorithms = (.) validationSettings validationSettingsAlgorithms validationSettingsValidationPolicy = (.) validationSettings validationSettingsValidationPolicy
+ Crypto.JOSE.JWS: class HasValidationSettings c_a1hPb where validationSettingsAlgorithms = (.) validationSettings validationSettingsAlgorithms validationSettingsValidationPolicy = (.) validationSettings validationSettingsValidationPolicy
- Crypto.JOSE.JWS: header :: forall a_a1gv0 a_a1gHk. Lens (Signature a_a1gv0) (Signature a_a1gHk) a_a1gv0 a_a1gHk
+ Crypto.JOSE.JWS: header :: forall a_a1gWm a_a1h8G. Lens (Signature a_a1gWm) (Signature a_a1h8G) a_a1gWm a_a1h8G
- Crypto.JOSE.JWS: jWSHeader :: HasJWSHeader c_a1gsn => Lens' c_a1gsn JWSHeader
+ Crypto.JOSE.JWS: jWSHeader :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ JWSHeader
- Crypto.JOSE.JWS: jwsHeaderAlg :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (HeaderParam Alg)
+ Crypto.JOSE.JWS: jwsHeaderAlg :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (HeaderParam Alg)
- Crypto.JOSE.JWS: jwsHeaderCrit :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (Maybe (NonEmpty Text))
+ Crypto.JOSE.JWS: jwsHeaderCrit :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (Maybe (NonEmpty Text))
- Crypto.JOSE.JWS: jwsHeaderCty :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (Maybe (HeaderParam String))
+ Crypto.JOSE.JWS: jwsHeaderCty :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (Maybe (HeaderParam String))
- Crypto.JOSE.JWS: jwsHeaderJku :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (Maybe (HeaderParam URI))
+ Crypto.JOSE.JWS: jwsHeaderJku :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (Maybe (HeaderParam URI))
- Crypto.JOSE.JWS: jwsHeaderJwk :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (Maybe (HeaderParam JWK))
+ Crypto.JOSE.JWS: jwsHeaderJwk :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (Maybe (HeaderParam JWK))
- Crypto.JOSE.JWS: jwsHeaderKid :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (Maybe (HeaderParam String))
+ Crypto.JOSE.JWS: jwsHeaderKid :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (Maybe (HeaderParam String))
- Crypto.JOSE.JWS: jwsHeaderTyp :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (Maybe (HeaderParam String))
+ Crypto.JOSE.JWS: jwsHeaderTyp :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (Maybe (HeaderParam String))
- Crypto.JOSE.JWS: jwsHeaderX5c :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (Maybe (HeaderParam (NonEmpty Base64X509)))
+ Crypto.JOSE.JWS: jwsHeaderX5c :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (Maybe (HeaderParam (NonEmpty Base64X509)))
- Crypto.JOSE.JWS: jwsHeaderX5t :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (Maybe (HeaderParam Base64SHA1))
+ Crypto.JOSE.JWS: jwsHeaderX5t :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (Maybe (HeaderParam Base64SHA1))
- Crypto.JOSE.JWS: jwsHeaderX5tS256 :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (Maybe (HeaderParam Base64SHA256))
+ Crypto.JOSE.JWS: jwsHeaderX5tS256 :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (Maybe (HeaderParam Base64SHA256))
- Crypto.JOSE.JWS: jwsHeaderX5u :: HasJWSHeader c_a1gsn => Lens' c_a1gsn (Maybe (HeaderParam URI))
+ Crypto.JOSE.JWS: jwsHeaderX5u :: HasJWSHeader c_a1gTJ => Lens' c_a1gTJ (Maybe (HeaderParam URI))
- Crypto.JOSE.JWS: validationSettings :: HasValidationSettings c_a1hnP => Lens' c_a1hnP ValidationSettings
+ Crypto.JOSE.JWS: validationSettings :: HasValidationSettings c_a1hPb => Lens' c_a1hPb ValidationSettings
- Crypto.JOSE.JWS: validationSettingsAlgorithms :: HasValidationSettings c_a1hnP => Lens' c_a1hnP (Set Alg)
+ Crypto.JOSE.JWS: validationSettingsAlgorithms :: HasValidationSettings c_a1hPb => Lens' c_a1hPb (Set Alg)
- Crypto.JOSE.JWS: validationSettingsValidationPolicy :: HasValidationSettings c_a1hnP => Lens' c_a1hnP ValidationPolicy
+ Crypto.JOSE.JWS: validationSettingsValidationPolicy :: HasValidationSettings c_a1hPb => Lens' c_a1hPb ValidationPolicy
- Crypto.JWT: _JWSError :: AsJWTError r_a1KwK => Prism' r_a1KwK Error
+ Crypto.JWT: _JWSError :: AsJWTError r_a1KYm => Prism' r_a1KYm Error
- Crypto.JWT: _JWTError :: AsJWTError r_a1KwK => Prism' r_a1KwK JWTError
+ Crypto.JWT: _JWTError :: AsJWTError r_a1KYm => Prism' r_a1KYm JWTError
- Crypto.JWT: _JWTExpired :: AsJWTError r_a1KwK => Prism' r_a1KwK ()
+ Crypto.JWT: _JWTExpired :: AsJWTError r_a1KYm => Prism' r_a1KYm ()
- Crypto.JWT: _JWTNotInAudience :: AsJWTError r_a1KwK => Prism' r_a1KwK ()
+ Crypto.JWT: _JWTNotInAudience :: AsJWTError r_a1KYm => Prism' r_a1KYm ()
- Crypto.JWT: _JWTNotYetValid :: AsJWTError r_a1KwK => Prism' r_a1KwK ()
+ Crypto.JWT: _JWTNotYetValid :: AsJWTError r_a1KYm => Prism' r_a1KYm ()
- Crypto.JWT: class AsJWTError r_a1KwK where _JWSError = (.) _JWTError _JWSError _JWTExpired = (.) _JWTError _JWTExpired _JWTNotYetValid = (.) _JWTError _JWTNotYetValid _JWTNotInAudience = (.) _JWTError _JWTNotInAudience
+ Crypto.JWT: class AsJWTError r_a1KYm where _JWSError = (.) _JWTError _JWSError _JWTExpired = (.) _JWTError _JWTExpired _JWTNotYetValid = (.) _JWTError _JWTNotYetValid _JWTNotInIssuer = (.) _JWTError _JWTNotInIssuer _JWTNotInAudience = (.) _JWTError _JWTNotInAudience _JWTIssuedAtFuture = (.) _JWTError _JWTIssuedAtFuture
- Crypto.JWT: class HasJWTValidationSettings c_a1L6X where jwtValidationSettingsAllowedSkew = (.) jWTValidationSettings jwtValidationSettingsAllowedSkew jwtValidationSettingsAudiencePredicate = (.) jWTValidationSettings jwtValidationSettingsAudiencePredicate jwtValidationSettingsValidationSettings = (.) jWTValidationSettings jwtValidationSettingsValidationSettings
+ Crypto.JWT: class HasJWTValidationSettings c_a1LAX where jwtValidationSettingsAllowedSkew = (.) jWTValidationSettings jwtValidationSettingsAllowedSkew jwtValidationSettingsAudiencePredicate = (.) jWTValidationSettings jwtValidationSettingsAudiencePredicate jwtValidationSettingsCheckIssuedAt = (.) jWTValidationSettings jwtValidationSettingsCheckIssuedAt jwtValidationSettingsIssuerPredicate = (.) jWTValidationSettings jwtValidationSettingsIssuerPredicate jwtValidationSettingsValidationSettings = (.) jWTValidationSettings jwtValidationSettingsValidationSettings
- Crypto.JWT: jWTValidationSettings :: HasJWTValidationSettings c_a1L6X => Lens' c_a1L6X JWTValidationSettings
+ Crypto.JWT: jWTValidationSettings :: HasJWTValidationSettings c_a1LAX => Lens' c_a1LAX JWTValidationSettings
- Crypto.JWT: jwtValidationSettingsAllowedSkew :: HasJWTValidationSettings c_a1L6X => Lens' c_a1L6X NominalDiffTime
+ Crypto.JWT: jwtValidationSettingsAllowedSkew :: HasJWTValidationSettings c_a1LAX => Lens' c_a1LAX NominalDiffTime
- Crypto.JWT: jwtValidationSettingsAudiencePredicate :: HasJWTValidationSettings c_a1L6X => Lens' c_a1L6X (StringOrURI -> Bool)
+ Crypto.JWT: jwtValidationSettingsAudiencePredicate :: HasJWTValidationSettings c_a1LAX => Lens' c_a1LAX (StringOrURI -> Bool)
- Crypto.JWT: jwtValidationSettingsValidationSettings :: HasJWTValidationSettings c_a1L6X => Lens' c_a1L6X ValidationSettings
+ Crypto.JWT: jwtValidationSettingsValidationSettings :: HasJWTValidationSettings c_a1LAX => Lens' c_a1LAX ValidationSettings
- Crypto.JWT: validateClaimsSet :: (MonadTime m, HasAllowedSkew a, HasAudiencePredicate a, AsJWTError e, MonadError e m) => a -> ClaimsSet -> m ()
+ Crypto.JWT: validateClaimsSet :: (MonadTime m, HasAllowedSkew a, HasAudiencePredicate a, HasIssuerPredicate a, HasCheckIssuedAt a, AsJWTError e, MonadError e m) => a -> ClaimsSet -> m ()
- Crypto.JWT: validateJWSJWT :: (MonadTime m, HasAllowedSkew a, HasAudiencePredicate a, HasValidationSettings a, AsError e, AsJWTError e, MonadError e m) => a -> JWK -> JWT -> m ()
+ Crypto.JWT: validateJWSJWT :: (MonadTime m, HasAllowedSkew a, HasAudiencePredicate a, HasIssuerPredicate a, HasCheckIssuedAt a, HasValidationSettings a, AsError e, AsJWTError e, MonadError e m) => a -> JWK -> JWT -> m ()

Files

jose.cabal view
@@ -1,14 +1,14 @@ name:                jose-version:             0.5.0.1+version:             0.5.0.2 synopsis:   Javascript Object Signing and Encryption and JSON Web Token library description:   .   An implementation of the Javascript Object Signing and Encryption-  (JOSE) and JSON Web Token (JWT; RFC 5717) formats.+  (JOSE) and JSON Web Token (JWT; RFC 7519) formats.   .-  The JSON Web Signature (JWS; RFC 5715) implementation is complete.-  JSON Web Encryption (JWE; RFC 5716) is not yet implemented.+  The JSON Web Signature (JWS; RFC 7515) implementation is complete.+  JSON Web Encryption (JWE; RFC 7516) is not yet implemented.   .   All JWS algorithms (HMAC, ECDSA, RSASSA-PKCS-v1_5 and RSASSA-PSS)   are implemented, however, the ECDSA implementation is is
src/Crypto/JWT.hs view
@@ -26,7 +26,7 @@ module Crypto.JWT   (     JWT(..)-+  , JWTCrypto(..)   , JWTError(..)   , AsJWTError(..) @@ -35,6 +35,8 @@   , HasJWTValidationSettings(..)   , HasAllowedSkew(..)   , HasAudiencePredicate(..)+  , HasIssuerPredicate(..)+  , HasCheckIssuedAt(..)    , createJWSJWT   , validateJWSJWT@@ -92,7 +94,9 @@   = JWSError Error   | JWTExpired   | JWTNotYetValid+  | JWTNotInIssuer   | JWTNotInAudience+  | JWTIssuedAtFuture   deriving (Eq, Show) makeClassyPrisms ''JWTError @@ -266,9 +270,11 @@ data JWTValidationSettings = JWTValidationSettings   { _jwtValidationSettingsValidationSettings :: ValidationSettings   , _jwtValidationSettingsAllowedSkew :: NominalDiffTime+  , _jwtValidationSettingsCheckIssuedAt :: Bool   -- ^ The allowed skew is interpreted in absolute terms;   --   a nonzero value always expands the validity period.   , _jwtValidationSettingsAudiencePredicate :: StringOrURI -> Bool+  , _jwtValidationSettingsIssuerPredicate :: StringOrURI -> Bool   } makeClassy ''JWTValidationSettings @@ -279,17 +285,27 @@   allowedSkew :: Lens' s NominalDiffTime class HasAudiencePredicate s where   audiencePredicate :: Lens' s (StringOrURI -> Bool)+class HasIssuerPredicate s where+  issuerPredicate :: Lens' s (StringOrURI -> Bool)+class HasCheckIssuedAt s where+  checkIssuedAt :: Lens' s Bool  instance HasJWTValidationSettings a => HasAllowedSkew a where   allowedSkew = jwtValidationSettingsAllowedSkew instance HasJWTValidationSettings a => HasAudiencePredicate a where   audiencePredicate = jwtValidationSettingsAudiencePredicate+instance HasJWTValidationSettings a => HasIssuerPredicate a where+  issuerPredicate = jwtValidationSettingsIssuerPredicate+instance HasJWTValidationSettings a => HasCheckIssuedAt a where+  checkIssuedAt = jwtValidationSettingsCheckIssuedAt  defaultJWTValidationSettings :: JWTValidationSettings defaultJWTValidationSettings = JWTValidationSettings   defaultValidationSettings   0+  False   (const False)+  (const True)  -- | Validate the claims made by a ClaimsSet. Currently only inspects -- the /exp/ and /nbf/ claims. N.B. These checks are also performed by@@ -299,6 +315,8 @@ validateClaimsSet   ::     ( MonadTime m, HasAllowedSkew a, HasAudiencePredicate a+    , HasIssuerPredicate a+    , HasCheckIssuedAt a     , AsJWTError e, MonadError e m     )   => a@@ -307,7 +325,9 @@ validateClaimsSet conf claims =   sequence_     [ validateExpClaim conf claims+    , validateIatClaim conf claims     , validateNbfClaim conf claims+    , validateIssClaim conf claims     , validateAudClaim conf claims     ] @@ -323,6 +343,18 @@     else throwError (review _JWTExpired ()) validateExpClaim _ _ = pure () +validateIatClaim+  :: (MonadTime m, HasCheckIssuedAt a, HasAllowedSkew a, AsJWTError e, MonadError e m)+  => a+  -> ClaimsSet+  -> m ()+validateIatClaim conf (ClaimsSet _ _ _ _ _ (Just t) _ _) = do+  now <- currentTime+  when (view checkIssuedAt conf) $+    when ((view _NumericDate t) > addUTCTime (abs (view allowedSkew conf)) now) $+    throwError (review _JWTIssuedAtFuture ())+validateIatClaim _ _ = pure ()+ validateNbfClaim   :: (MonadTime m, HasAllowedSkew a, AsJWTError e, MonadError e m)   => a@@ -350,6 +382,20 @@       )     (preview (claimAud . _Just . _Audience) claims) +validateIssClaim+  :: (HasIssuerPredicate s, AsJWTError e, MonadError e m)+  => s+  -> ClaimsSet+  -> m ()+validateIssClaim conf claims =+  maybe+    (pure ())+    (\iss ->+      if view issuerPredicate conf iss+      then pure ()+      else throwError (review _JWTNotInIssuer ())+      )+    (preview (claimIss . _Just) claims)  -- | Data representing the JOSE aspects of a JWT. --@@ -386,6 +432,8 @@ validateJWSJWT   ::     ( MonadTime m, HasAllowedSkew a, HasAudiencePredicate a+    , HasIssuerPredicate a+    , HasCheckIssuedAt a     , HasValidationSettings a     , AsError e, AsJWTError e, MonadError e m     )
test/JWT.hs view
@@ -107,6 +107,45 @@           in runReaderT (validateClaimsSet conf' exampleClaimsSet) now             `shouldBe` (Right () :: Either JWTError ()) +    describe "with an Issued At claim" $ do+      let claimsSetWithIat = set claimIat (intDate "2011-02-22 18:43:00") emptyClaimsSet+      let conf = set checkIssuedAt True defaultJWTValidationSettings++      describe "when the current time is after to the Issued At" $ do+        let now = utcTime "2011-03-01 00:00:00"+        it "can be validated" $+          runReaderT (validateClaimsSet conf claimsSetWithIat) now+            `shouldBe` (Right () :: Either JWTError ())++      describe "when the current time is exactly the Issued At" $ do+        let now = utcTime "2011-02-22 18:43:00"+        it "can be validated" $+          runReaderT (validateClaimsSet conf claimsSetWithIat) now+            `shouldBe` (Right () :: Either JWTError ())++      describe "when the current time is prior to the Issued At" $ do+        let now = utcTime "2011-02-22 18:42:59"  -- 1s before issued at+        it "cannot be validated if nonzero skew tolerance < delta" $+          let conf' = set allowedSkew 0 conf+          in runReaderT (validateClaimsSet conf' claimsSetWithIat) now+            `shouldBe` Left JWTIssuedAtFuture+        it "can be validated if nonzero skew tolerance < delta but validation is off" $+          let conf' = set checkIssuedAt False conf+          in runReaderT (validateClaimsSet conf' claimsSetWithIat) now+            `shouldBe` (Right () :: Either JWTError ())+        it "can be validated if nonzero skew tolerance = delta" $+          let conf' = set allowedSkew 1 conf+          in runReaderT (validateClaimsSet conf' claimsSetWithIat) now+            `shouldBe` (Right () :: Either JWTError ())+        it "can be validated if nonzero skew tolerance > delta" $+          let conf' = set allowedSkew 2 conf+          in runReaderT (validateClaimsSet conf' claimsSetWithIat) now+            `shouldBe` (Right () :: Either JWTError ())+        it "can be validated if negative skew tolerance = -delta" $+          let conf' = set allowedSkew (-1) conf+          in runReaderT (validateClaimsSet conf' claimsSetWithIat) now+            `shouldBe` (Right () :: Either JWTError ())+     describe "with a Not Before claim" $ do       let         claimsSet = emptyClaimsSet & claimNbf .~ intDate "2016-07-05 17:37:22"@@ -196,6 +235,25 @@         let claims = emptyClaimsSet & set claimAud (Just (Audience ["foo"]))         it "serialises to string" $ encode claims `shouldBe` "{\"aud\":\"foo\"}"         it "round trips" $ decode (encode claims) `shouldBe` Just claims++    describe "with an Issuer claim" $ do+      let now = utcTime "2001-01-01 00:00:00"+      let conf' = set issuerPredicate (== "baz") conf+      describe "when issuer is nonempty, and predicate is matched" $ do+        let claims = emptyClaimsSet & set claimIss (Just "baz")+        it "can be validated" $+          runReaderT (validateClaimsSet conf' claims) now+            `shouldBe` (Right () :: Either JWTError ())+      describe "when issuer is nonempty but predicate is not matched" $ do+        let claims = emptyClaimsSet & set claimIss (Just "bar")+        it "cannot be validated" $+          runReaderT (validateClaimsSet conf' claims) now+            `shouldBe` Left JWTNotInIssuer+      describe "when claim is empty, and default predicate is unconditionally true" $ do+        let claims = emptyClaimsSet & set claimIss (Just "")+        it "can be validated" $+          runReaderT (validateClaimsSet conf claims) now+            `shouldBe` (Right () :: Either JWTError ())    describe "StringOrURI" $     it "parses from JSON correctly" $ do