| Safe Haskell | None |
|---|---|
| Language | Haskell98 |
Crypto.JWT
Contents
Description
JSON Web Token implementation (RFC 7519). A JWT is a JWS with a payload of claims to be transferred between two parties.
JWTs use the JWS compact serialisation. See Crypto.JOSE.Compact for details.
mkClaims :: IOClaimsSetmkClaims = do t <-currentTimepure $emptyClaimsSet&claimIss.~ Just ("alice") &claimAud.~ Just (Audience["bob"]) &claimIat.~ Just (NumericDatet) doJwtSign ::JWK->ClaimsSet-> IO (EitherJWTErrorSignedJWT) doJwtSign jwk claims = runExceptT $ do alg <-bestJWSAlgjwksignClaimsjwk (newJWSHeader((), alg)) claims doJwtVerify ::JWK->SignedJWT-> IO (EitherJWTErrorClaimsSet) doJwtVerify jwk jwt = runExceptT $ do let config =defaultJWTValidationSettings(== "bob")verifyClaimsconfig jwk jwt
Some JWT libraries have a function that takes two strings: the "secret" (a symmetric key) and the raw JWT. The following function achieves the same:
verify :: L.ByteString -> L.ByteString -> IO (EitherJWTErrorClaimsSet) verify k s = runExceptT $ do let k' =fromOctetsk -- turn raw secret into symmetric JWK audCheck = const True -- should be a proper audience check s' <-decodeCompacts -- decode JWTverifyClaims(defaultJWTValidationSettingsaudCheck) k' s'
Synopsis
- signClaims :: (MonadRandom m, MonadError e m, AsError e) => JWK -> JWSHeader () -> ClaimsSet -> m SignedJWT
- type SignedJWT = CompactJWS JWSHeader
- defaultJWTValidationSettings :: (StringOrURI -> Bool) -> JWTValidationSettings
- verifyClaims :: (MonadTime m, HasAllowedSkew a, HasAudiencePredicate a, HasIssuerPredicate a, HasCheckIssuedAt a, HasValidationSettings a, AsError e, AsJWTError e, MonadError e m, VerificationKeyStore m (JWSHeader ()) ClaimsSet k) => a -> k -> SignedJWT -> m ClaimsSet
- verifyClaimsAt :: (HasAllowedSkew a, HasAudiencePredicate a, HasIssuerPredicate a, HasCheckIssuedAt a, HasValidationSettings a, AsError e, AsJWTError e, MonadError e m, VerificationKeyStore (ReaderT WrappedUTCTime m) (JWSHeader ()) ClaimsSet k) => a -> k -> UTCTime -> SignedJWT -> m ClaimsSet
- class HasAllowedSkew s where
- 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
- data JWTValidationSettings
- class HasJWTValidationSettings c where
- jWTValidationSettings :: Lens' c JWTValidationSettings
- jwtValidationSettingsAllowedSkew :: Lens' c NominalDiffTime
- jwtValidationSettingsAudiencePredicate :: Lens' c (StringOrURI -> Bool)
- jwtValidationSettingsCheckIssuedAt :: Lens' c Bool
- jwtValidationSettingsIssuerPredicate :: Lens' c (StringOrURI -> Bool)
- jwtValidationSettingsValidationSettings :: Lens' c ValidationSettings
- data ClaimsSet
- claimAud :: Lens' ClaimsSet (Maybe Audience)
- claimExp :: Lens' ClaimsSet (Maybe NumericDate)
- claimIat :: Lens' ClaimsSet (Maybe NumericDate)
- claimIss :: Lens' ClaimsSet (Maybe StringOrURI)
- claimJti :: Lens' ClaimsSet (Maybe Text)
- claimNbf :: Lens' ClaimsSet (Maybe NumericDate)
- claimSub :: Lens' ClaimsSet (Maybe StringOrURI)
- unregisteredClaims :: Lens' ClaimsSet (HashMap Text Value)
- addClaim :: Text -> Value -> ClaimsSet -> ClaimsSet
- emptyClaimsSet :: ClaimsSet
- validateClaimsSet :: (MonadTime m, HasAllowedSkew a, HasAudiencePredicate a, HasIssuerPredicate a, HasCheckIssuedAt a, AsJWTError e, MonadError e m) => a -> ClaimsSet -> m ClaimsSet
- data JWTError
- class AsJWTError r where
- _JWTError :: Prism' r JWTError
- _JWSError :: Prism' r Error
- _JWTClaimsSetDecodeError :: Prism' r String
- _JWTExpired :: Prism' r ()
- _JWTNotYetValid :: Prism' r ()
- _JWTNotInIssuer :: Prism' r ()
- _JWTNotInAudience :: Prism' r ()
- _JWTIssuedAtFuture :: Prism' r ()
- newtype Audience = Audience [StringOrURI]
- data StringOrURI
- stringOrUri :: (Cons s s Char Char, AsEmpty s) => Prism' s StringOrURI
- string :: Prism' StringOrURI Text
- uri :: Prism' StringOrURI URI
- newtype NumericDate = NumericDate UTCTime
- module Crypto.JOSE
Creating a JWT
signClaims :: (MonadRandom m, MonadError e m, AsError e) => JWK -> JWSHeader () -> ClaimsSet -> m SignedJWT #
Create a JWS JWT
type SignedJWT = CompactJWS JWSHeader #
A digitally signed or MACed JWT
Validating a JWT and extracting claims
defaultJWTValidationSettings :: (StringOrURI -> Bool) -> JWTValidationSettings #
Acquire the default validation settings.
RFC 7519 §4.1.3. states that applications MUST identify itself with a value in the audience claim, therefore a predicate must be supplied.
The other defaults are:
defaultValidationSettingsfor JWS verification- Zero clock skew tolerance when validating nbf, exp and iat claims
- iat claim is checked
- issuer claim is not checked
verifyClaims :: (MonadTime m, HasAllowedSkew a, HasAudiencePredicate a, HasIssuerPredicate a, HasCheckIssuedAt a, HasValidationSettings a, AsError e, AsJWTError e, MonadError e m, VerificationKeyStore m (JWSHeader ()) ClaimsSet k) => a -> k -> SignedJWT -> m ClaimsSet #
Cryptographically verify a JWS JWT, then validate the Claims Set, returning it if valid.
This is the only way to get at the claims of a JWS JWT, enforcing that the claims are cryptographically and semantically valid before the application can use them.
See also verifyClaimsAt which allows you to explicitly specify
the time.
verifyClaimsAt :: (HasAllowedSkew a, HasAudiencePredicate a, HasIssuerPredicate a, HasCheckIssuedAt a, HasValidationSettings a, AsError e, AsJWTError e, MonadError e m, VerificationKeyStore (ReaderT WrappedUTCTime m) (JWSHeader ()) ClaimsSet k) => a -> k -> UTCTime -> SignedJWT -> m ClaimsSet #
Cryptographically verify a JWS JWT, then validate the Claims Set, returning it if valid.
This is the same as verifyClaims except that the time is
explicitly provided. If you process many requests per second
this will allow you to avoid unnecessary repeat system calls.
class HasAllowedSkew s where #
Maximum allowed skew when validating the nbf, exp and iat claims.
Methods
allowedSkew :: Lens' s NominalDiffTime #
Instances
| HasJWTValidationSettings a => HasAllowedSkew a # | |
Defined in Crypto.JWT Methods allowedSkew :: Lens' a NominalDiffTime # | |
class HasAudiencePredicate s where #
Predicate for checking values in the aud claim.
Methods
audiencePredicate :: Lens' s (StringOrURI -> Bool) #
Instances
| HasJWTValidationSettings a => HasAudiencePredicate a # | |
Defined in Crypto.JWT Methods audiencePredicate :: Lens' a (StringOrURI -> Bool) # | |
class HasIssuerPredicate s where #
Predicate for checking the iss claim.
Methods
issuerPredicate :: Lens' s (StringOrURI -> Bool) #
Instances
| HasJWTValidationSettings a => HasIssuerPredicate a # | |
Defined in Crypto.JWT Methods issuerPredicate :: Lens' a (StringOrURI -> Bool) # | |
class HasCheckIssuedAt s where #
Whether to check that the iat claim is not in the future.
Methods
checkIssuedAt :: Lens' s Bool #
Instances
| HasJWTValidationSettings a => HasCheckIssuedAt a # | |
Defined in Crypto.JWT Methods checkIssuedAt :: Lens' a Bool # | |
data JWTValidationSettings #
Instances
class HasJWTValidationSettings c where #
Minimal complete definition
Methods
jWTValidationSettings :: Lens' c JWTValidationSettings #
jwtValidationSettingsAllowedSkew :: Lens' c NominalDiffTime #
jwtValidationSettingsAudiencePredicate :: Lens' c (StringOrURI -> Bool) #
jwtValidationSettingsCheckIssuedAt :: Lens' c Bool #
jwtValidationSettingsIssuerPredicate :: Lens' c (StringOrURI -> Bool) #
jwtValidationSettingsValidationSettings :: Lens' c ValidationSettings #
Instances
Claims Set
The JWT Claims Set represents a JSON object whose members are
the registered claims defined by RFC 7519. Unrecognised
claims are gathered into the unregisteredClaims map.
claimAud :: Lens' ClaimsSet (Maybe Audience) #
The audience claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the aud claim when this claim is present, then the JWT MUST be rejected.
claimExp :: Lens' ClaimsSet (Maybe NumericDate) #
The expiration time claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of exp claim requires that the current date/time MUST be before expiration date/time listed in the exp claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.
claimIat :: Lens' ClaimsSet (Maybe NumericDate) #
The issued at claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT.
claimIss :: Lens' ClaimsSet (Maybe StringOrURI) #
The issuer claim identifies the principal that issued the JWT. The processing of this claim is generally application specific.
claimJti :: Lens' ClaimsSet (Maybe Text) #
The JWT ID claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object. The jti claim can be used to prevent the JWT from being replayed. The jti value is a case-sensitive string.
claimNbf :: Lens' ClaimsSet (Maybe NumericDate) #
The not before claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the nbf claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the nbf claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.
claimSub :: Lens' ClaimsSet (Maybe StringOrURI) #
The subject claim identifies the principal that is the subject of the JWT. The Claims in a JWT are normally statements about the subject. The subject value MAY be scoped to be locally unique in the context of the issuer or MAY be globally unique. The processing of this claim is generally application specific.
unregisteredClaims :: Lens' ClaimsSet (HashMap Text Value) #
Claim Names can be defined at will by those using JWTs.
Return an empty claims set.
validateClaimsSet :: (MonadTime m, HasAllowedSkew a, HasAudiencePredicate a, HasIssuerPredicate a, HasCheckIssuedAt a, AsJWTError e, MonadError e m) => a -> ClaimsSet -> m ClaimsSet #
Validate the claims made by a ClaimsSet.
These checks are performed by verifyClaims, which also
validates any signatures, so you shouldn't need to use this
function directly.
JWT errors
Constructors
| JWSError Error | A JOSE error occurred while processing the JWT |
| JWTClaimsSetDecodeError String | The JWT payload is not a JWT Claims Set |
| JWTExpired | |
| JWTNotYetValid | |
| JWTNotInIssuer | |
| JWTNotInAudience | |
| JWTIssuedAtFuture |
Instances
class AsJWTError r where #
Minimal complete definition
Methods
_JWTError :: Prism' r JWTError #
_JWTClaimsSetDecodeError :: Prism' r String #
_JWTExpired :: Prism' r () #
_JWTNotYetValid :: Prism' r () #
_JWTNotInIssuer :: Prism' r () #
_JWTNotInAudience :: Prism' r () #
_JWTIssuedAtFuture :: Prism' r () #
Instances
| AsJWTError JWTError # | |
Defined in Crypto.JWT Methods _JWTError :: Prism' JWTError JWTError # _JWSError :: Prism' JWTError Error # _JWTClaimsSetDecodeError :: Prism' JWTError String # _JWTExpired :: Prism' JWTError () # _JWTNotYetValid :: Prism' JWTError () # _JWTNotInIssuer :: Prism' JWTError () # _JWTNotInAudience :: Prism' JWTError () # _JWTIssuedAtFuture :: Prism' JWTError () # | |
Miscellaneous
Audience data. 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.
The ToJSON instance formats an Audience with one value as a
string (some non-compliant implementations require this.)
Constructors
| Audience [StringOrURI] |
data 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.
Note: the IsString instance will fail if the string
contains a : but does not parse as a URI. Use stringOrUri
directly in this situation.
Instances
| Eq StringOrURI # | |
Defined in Crypto.JWT | |
| Show StringOrURI # | |
Defined in Crypto.JWT Methods showsPrec :: Int -> StringOrURI -> ShowS # show :: StringOrURI -> String # showList :: [StringOrURI] -> ShowS # | |
| IsString StringOrURI # | Non-total. A string with a |
Defined in Crypto.JWT Methods fromString :: String -> StringOrURI # | |
| ToJSON StringOrURI # | |
Defined in Crypto.JWT Methods toJSON :: StringOrURI -> Value # toEncoding :: StringOrURI -> Encoding # toJSONList :: [StringOrURI] -> Value # toEncodingList :: [StringOrURI] -> Encoding # | |
| FromJSON StringOrURI # | |
Defined in Crypto.JWT | |
stringOrUri :: (Cons s s Char Char, AsEmpty s) => Prism' s StringOrURI #
string :: Prism' StringOrURI Text #
uri :: Prism' StringOrURI URI #
newtype NumericDate #
A JSON numeric value representing the number of seconds from 1970-01-01T0:0:0Z UTC until the specified UTC date/time.
Constructors
| NumericDate UTCTime |
Instances
| Eq NumericDate # | |
Defined in Crypto.JWT | |
| Ord NumericDate # | |
Defined in Crypto.JWT Methods compare :: NumericDate -> NumericDate -> Ordering # (<) :: NumericDate -> NumericDate -> Bool # (<=) :: NumericDate -> NumericDate -> Bool # (>) :: NumericDate -> NumericDate -> Bool # (>=) :: NumericDate -> NumericDate -> Bool # max :: NumericDate -> NumericDate -> NumericDate # min :: NumericDate -> NumericDate -> NumericDate # | |
| Show NumericDate # | |
Defined in Crypto.JWT Methods showsPrec :: Int -> NumericDate -> ShowS # show :: NumericDate -> String # showList :: [NumericDate] -> ShowS # | |
| ToJSON NumericDate # | |
Defined in Crypto.JWT Methods toJSON :: NumericDate -> Value # toEncoding :: NumericDate -> Encoding # toJSONList :: [NumericDate] -> Value # toEncodingList :: [NumericDate] -> Encoding # | |
| FromJSON NumericDate # | |
Defined in Crypto.JWT | |
module Crypto.JOSE