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 +4/−4
- src/Crypto/JWT.hs +49/−1
- test/JWT.hs +58/−0
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