jose-jwt
JSON Object Signing and Encryption Library
http://github.com/tekul/jose-jwt
LTS Haskell 22.33: | 0.9.6 |
Stackage Nightly 2024-09-07: | 0.10.0 |
Latest on Hackage: | 0.10.0 |
jose-jwt-0.10.0@sha256:6ed175a01c721e317ceea15eb251a81de145c03711a977517935633a5cdec1d4,3546
Module documentation for 0.10.0
- Jose
- Jose.Internal
- Jose.Internal.Base64
- Jose.Internal.Crypto
- Jose.Internal.Parser
- Jose.Jwa
- Jose.Jwe
- Jose.Jwk
- Jose.Jws
- Jose.Jwt
- Jose.Internal
jose-jwt
A Haskell implementation of the JSON Object Signing and Encryption (JOSE) specifications and the related JWT specification, as used, for example, in OpenID Connect.
Background
The JWT specification was split into JWS
and JWE
during its development so does not contain much. A JWT is either a JWS or a JWE depending on whether it is signed or encrypted. It is encoded as a sequence of base64 strings separated by ‘.’ characters [1].
Technically, the content of a JWT should be JSON (unless it’s a nested JWT), but this library doesn’t care - it only requires a bytestring. The application should verify that the content is valid. Exactly what that means will depend on what you are using JWTs for.
Examples
You can either use the high-level encode
and decode
functions in the Jwt
module or specific functions in the Jws
and Jwe
modules.
The following examples can be entered directly into ghci
. Use
> :set -XOverloadedStrings
to begin with.
JWS signing example with a symmetric HMAC algorithm
HMAC is a good choice when both signer and verifier have a copy of the key.
> import Jose.Jws (hmacEncode, hmacDecode)
> import Jose.Jwa (JwsAlg(HS256))
>
> hmacEncode HS256 "aRANDOMlygeneratedkey" "my JSON message"
Right (Jwt {unJwt = "eyJhbGciOiJIUzI1NiJ9.bXkgSlNPTiBtZXNzYWdl.lTJx7ECLwYF3P7WbrrUpcp_2SdLiFXaDwK-PXcipt5Q"})
> hmacDecode "aRANDOMlygeneratedkey" "eyJhbGciOiJIUzI1NiJ9.bXkgSlNPTiBtZXNzYWdl.lTJx7ECLwYF3P7WbrrUpcp_2SdLiFXaDwK-PXcipt5Q"
Right (JwsHeader {jwsAlg = HS256, jwsTyp = Nothing, jwsCty = Nothing, jwsKid = Nothing},"my JSON message")
Trying to decode with a different key would return a Left BadSignature
[2].
JWS signing using Ed25519 private key
Some situations require the use of public key cryptography for signing. For example, only a trusted party is allowed to create a signed token, but it must be verified by others.
Elliptic-curve EdDSA signing and verification are supported as defined in RFC 8037, as well as the older RSA JWS algorithms.
> import Jose.Jwt
> import Jose.Jwk
> import Jose.Jwa (JwsAlg(EdDSA))
> import Data.ByteString (ByteString)
> import Data.Aeson (decodeStrict)
>
> jsonJwk = "{\"kty\":\"OKP\", \"crv\":\"Ed25519\", \"d\":\"nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A\", \"x\":\"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo\"}" :: ByteString
> Just jwk = decodeStrict jsonJwk :: Maybe Jwk
> Jose.Jwt.encode [jwk] (JwsEncoding EdDSA) (Claims "public claims")
Right (Jwt {unJwt = "eyJhbGciOiJFZERTQSJ9.cHVibGljIGNsYWltcw.xYekeeGSQVpnQbl16lOCqFcmYsUj3goSTrZ4UBQqogjHLrvFUaVJ_StBqly-Tb-0xvayjUMM4INYBTwFMt_xAQ"})
To verify the JWT you would use the Jose.Jwt.decode
function with the corresponding public key.
More examples can be found in the package documentation.
Build Status
[1] This is now referred to as “compact serialization”. The additional “JSON serialization” is not supported in this library.
[2] Note that a real key for HMAC256 should be a much longer, random string of bytes. See, for example, this stackexchange answer.
Changes
0.10.0
- Change to using crypton (see #41).
0.9.6
- Updated aeson package bound to include 2.2
0.9.5
- Support for mtl 2.3
0.9.4
- Support for aeson 2
0.9.3
- Add upper bound < 1.6 for aeson dependency
- Add Num Instance for IntDate
0.9.2
- Add
UnsupportedJwt
constructor toJwk
type which wraps the JSON value. This prevents failure loading keys which havealg
orkty
values which we don’t support (see #31).
0.9.1
- Fix for tests broken due to different aeson key ordering.
0.9.0
- Support for EdDSA signing algorithms as defined in RFC 8037.
0.8.0
- The result of the
Jose.Jwt.decodeClaims
function is now polymorphic so it can be used with anyFromJSON
type. - Only ghc 8 upwards are now supported.
- the RSA-OAEP-256 algorithm is now supported.
0.7.8
- Switch from EitherT to ExceptT to allow compiling with latest version of ‘either’ package.
0.7.7
- User ByteArray and ScrubbedBytes from memory package in preference to ByteString in internal crypto code.
0.7.6
- Fixed exception when JWT contained invalid Base64 (issue #15).
- Add generateSymmetricKey utility function to Jwk module.
0.7.5
- A JWT parser is now used to separate parsing and decoding into separate stages (internal change).
0.7.4
- Stricter checking of AES key lengths when looking for a valid JWK to encode/decode an AES-KW JWT.
0.7.3
- Add JSON test data to extra-source-files.
0.7.2
- Remove test dependency on aeson-qq
0.7.1
- Update cryptonite version to 0.19 to avoid security issues
- Fix broken benchmark code
- Better error message for invalid key length when using AES keywrap
0.7
- Add support for AES key wrap in JWEs.
- Support A192GCM and A192CBC-HS384 algorithms.
- Switch to cryptonite library.
0.6.2
- Remove dependency on
errors
package.
0.6.1
- Minor internal changes to fix build on GHC 7.10.
0.6
- Change KeyId type to allow use of a UTCTime string for the identifier.
- Internal crypto fixes to prevent exceptions from external libraries.
0.5
- Add JwtEncoding type. Changes API of
Jwt.encode
andJwt.decode
.
0.4.2
- Fix in the code for finding suitable JWKs for encoding/decoding.
0.4.1.1
- Added
doctest
flag to cabal file to allow doctests to be disabled.
0.4.1
- Add cprng-aes dependency to doctests to stop test failure on travis and nixos hydra builds.
0.4
- Changed use of
Jwt
type to represent an encoded JWT. - Introduced
Payload
type to allow setting thecty
header value correctly for nested JWTs. - Added an explicit
Unsecured
type for a decoded JWT, to make it obvious when the content is not signed or encrypted. - Fixed some bugs in JSON encoding and decoding of EC JWKs.
0.3.1
Changed the signature of Jwt.encode
to take a list of Jwk
rather than a single key. The key will be selected from
the list based on the specified algorithms.
0.3
- New support for JWS validation using elliptic curve algorithms.
- Added
Jwt.encode
function which takes a JWK argument, allowing key data (currently the key ID) to be encoded in the token header.