diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.9.4
+-----
+
+* Support for aeson 2
+
 0.9.3
 -----
 
diff --git a/Jose/Jwk.hs b/Jose/Jwk.hs
--- a/Jose/Jwk.hs
+++ b/Jose/Jwk.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE OverloadedStrings, DeriveGeneric, RecordWildCards #-}
+{-# LANGUAGE OverloadedStrings, DeriveGeneric, RecordWildCards, CPP #-}
 {-# OPTIONS_HADDOCK prune #-}
 
 module Jose.Jwk
@@ -30,11 +30,15 @@
 import qualified Crypto.PubKey.ECC.Types as ECC
 import           Crypto.Number.Serialize
 import           Data.Aeson (fromJSON, genericToJSON, Object, Result(..), Value(..), FromJSON(..), ToJSON(..), withText)
+#if MIN_VERSION_aeson(2,0,0)
+import qualified Data.Aeson.KeyMap as KM
+#else
+import qualified Data.HashMap.Strict as H
+#endif
 import           Data.Aeson.Types (Parser, Options (..), defaultOptions)
 import qualified Data.ByteArray as BA
 import           Data.ByteString (ByteString)
 import qualified Data.ByteString as B
-import qualified Data.HashMap.Strict as H
 import           Data.Maybe (isNothing, fromMaybe)
 import           Data.Text (Text)
 import qualified Data.Text.Encoding as TE
@@ -305,10 +309,15 @@
                 Right jwk -> return jwk
         _ -> pure (UnsupportedJwk k)
   where
-    algValue = fromMaybe Null (H.lookup "alg" k)
+#if MIN_VERSION_aeson(2,0,0)
+    algValue = fromMaybe Null (KM.lookup "alg" k)
     -- kty is required so if it's missing here we do nothing and allow decoding to fail
     -- later
+    ktyValue = fromMaybe Null (KM.lookup "kty" k)
+#else
+    algValue = fromMaybe Null (H.lookup "alg" k)
     ktyValue = fromMaybe Null (H.lookup "kty" k)
+#endif
     checkAlg = fromJSON algValue :: Result (Maybe Alg)
     checkKty = fromJSON ktyValue :: Result (Maybe KeyType)
 
diff --git a/Jose/Types.hs b/Jose/Types.hs
--- a/Jose/Types.hs
+++ b/Jose/Types.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE OverloadedStrings, DeriveGeneric, FlexibleContexts, GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE OverloadedStrings, DeriveGeneric, FlexibleContexts, GeneralizedNewtypeDeriving, CPP #-}
 {-# OPTIONS_HADDOCK prune #-}
 
 module Jose.Types
@@ -23,10 +23,14 @@
 where
 
 import Data.Aeson
+#if MIN_VERSION_aeson(2,0,0)
+import Data.Aeson.KeyMap as KM
+#else
+import qualified Data.HashMap.Strict as H
+#endif
 import Data.Char (toUpper, toLower)
 import Data.ByteString (ByteString)
 import qualified Data.ByteString.Lazy as BL
-import qualified Data.HashMap.Strict as H
 import Data.Int (Int64)
 import Data.Time.Clock (UTCTime)
 import Data.Time.Clock.POSIX
@@ -126,8 +130,13 @@
 
 -- Deal with the case where "aud" may be a single value rather than an array
 instance FromJSON JwtClaims where
+#if MIN_VERSION_aeson(2,0,0)
+    parseJSON v@(Object o) = case KM.lookup "aud" o of
+        Just (a@(String _)) -> genericParseJSON claimsOptions $ Object $ KM.insert "aud" (Array $ Data.Vector.singleton a) o
+#else
     parseJSON v@(Object o) = case H.lookup "aud" o of
         Just (a@(String _)) -> genericParseJSON claimsOptions $ Object $ H.insert "aud" (Array $ singleton a) o
+#endif
         _                   -> genericParseJSON claimsOptions v
     parseJSON _            = fail "JwtClaims must be an object"
 
@@ -174,9 +183,15 @@
     parseJSON = genericParseJSON jweOptions
 
 instance FromJSON JwtHeader where
+#if MIN_VERSION_aeson(2,0,0)
+    parseJSON v@(Object o) = case KM.lookup "alg" o of
+        Just (String "none") -> pure UnsecuredH
+        _                    -> case KM.lookup "enc" o of
+#else
     parseJSON v@(Object o) = case H.lookup "alg" o of
         Just (String "none") -> pure UnsecuredH
         _                    -> case H.lookup "enc" o of
+#endif
             Nothing -> JwsH <$> parseJSON v
             _       -> JweH <$> parseJSON v
     parseJSON _            = fail "JwtHeader must be an object"
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -4,9 +4,9 @@
 
 ## Background
 
-The [JWT specification](https://tools.ietf.org/html/rfc7519) was split into [`JWS`](https://www.rfc-editor.org/rfc/rfc7515.html) and [`JWE`](https://www.rfc-editor.org/rfc/rfc7515.html) during its development and thus does not contain much. Basically, 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].
+The [JWT specification](https://tools.ietf.org/html/rfc7519) was split into [`JWS`](https://www.rfc-editor.org/rfc/rfc7515.html) and [`JWE`](https://www.rfc-editor.org/rfc/rfc7516.html) 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 the library doesn't care - it only requires a bytestring. The calling application should verify that the content is valid. Exactly what that means will depend on what you are using JWTs for.
+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
 
diff --git a/jose-jwt.cabal b/jose-jwt.cabal
--- a/jose-jwt.cabal
+++ b/jose-jwt.cabal
@@ -1,5 +1,5 @@
 Name:               jose-jwt
-Version:            0.9.3
+Version:            0.9.4
 Synopsis:           JSON Object Signing and Encryption Library
 Homepage:           http://github.com/tekul/jose-jwt
 Bug-Reports:        http://github.com/tekul/jose-jwt/issues
@@ -50,7 +50,7 @@
     Buildable: False
   else
     Build-depends:    base >= 4.9 && < 5
-                    , aeson >= 1.5 && < 1.6
+                    , aeson >= 1.5 && < 2.1
                     , attoparsec >= 0.12.0.0
                     , bytestring >= 0.9
                     , cereal >= 0.4
diff --git a/tests/Tests/JwkSpec.hs b/tests/Tests/JwkSpec.hs
--- a/tests/Tests/JwkSpec.hs
+++ b/tests/Tests/JwkSpec.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings, CPP #-}
 
 module Tests.JwkSpec where
 
@@ -6,8 +6,12 @@
 import Test.HUnit hiding (Test)
 
 import Data.Aeson
-import qualified Data.ByteString.Char8 as B
+#if MIN_VERSION_aeson(2,0,0)
+import qualified Data.Aeson.KeyMap as KM
+#else
 import qualified Data.HashMap.Strict as H
+#endif
+import qualified Data.ByteString.Char8 as B
 import Data.Word (Word64)
 import qualified Data.Vector as V
 import Crypto.PubKey.ECC.ECDSA
@@ -73,10 +77,18 @@
             assertBool "Different keys should be unequal" (k0 /= k1)
 
     describe "Errors in JWK data" $ do
+#if MIN_VERSION_aeson(2,0,0)
+        let Just (Array ks) = KM.lookup "keys" keySet
+#else
         let Just (Array ks) = H.lookup "keys" keySet
+#endif
             Object k0obj = V.head ks
         it "invalid Base64 returns an error" $ do
+#if MIN_VERSION_aeson(2,0,0)
+            let result = fromJSON (Object $ KM.insert "n" (String "NotBase64**") k0obj) :: Result Jwk
+#else
             let result = fromJSON (Object $ H.insert "n" (String "NotBase64**") k0obj) :: Result Jwk
+#endif
             case result of
                 Error _ -> assertBool "" True
                 _       -> assertFailure "Expected an error for invalid base 64"
