diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,13 @@
-## [*Unreleased*](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.6.1.2...master)
+## [*Unreleased*](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.6.1.3...master)
 
 None
+
+## [v0.6.1.3](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.6.1.2...v0.6.1.3)
+
+- Replace `System.Random` state token generation with `cryptonite`
+- Allow aeson-1.5 and hoauth2-1.14
+- Add WordPress.com provider
+  [@nbloomf](https://github.com/thoughtbot/yesod-auth-oauth2/pull/130)
 
 ## [v0.6.1.2](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.6.1.1...v0.6.1.2)
 
diff --git a/example/Main.hs b/example/Main.hs
--- a/example/Main.hs
+++ b/example/Main.hs
@@ -26,7 +26,6 @@
 import Data.ByteString.Lazy (fromStrict, toStrict)
 import qualified Data.Map as M
 import Data.Maybe (fromJust)
-import Data.Monoid ((<>))
 import Data.Text (Text)
 import qualified Data.Text as T
 import Data.Text.Encoding (decodeUtf8)
@@ -36,6 +35,7 @@
 import System.Environment (getEnv)
 import Yesod
 import Yesod.Auth
+import Yesod.Auth.OAuth2.AzureAD
 import Yesod.Auth.OAuth2.BattleNet
 import Yesod.Auth.OAuth2.Bitbucket
 import Yesod.Auth.OAuth2.EveOnline
@@ -46,6 +46,7 @@
 import Yesod.Auth.OAuth2.Salesforce
 import Yesod.Auth.OAuth2.Slack
 import Yesod.Auth.OAuth2.Spotify
+import Yesod.Auth.OAuth2.WordPressDotCom
 import Yesod.Auth.OAuth2.Upcase
 
 data App = App
@@ -84,6 +85,8 @@
 instance RenderMessage App FormMessage where
     renderMessage _ _ = defaultFormMessage
 
+-- brittany-disable-next-binding
+
 getRootR :: Handler Html
 getRootR = do
     sess <- getSession
@@ -132,7 +135,8 @@
         --
         -- FIXME: oauth2BattleNet is quite annoying!
         --
-        [ loadPlugin (oauth2BattleNet [whamlet|TODO|] "en") "BATTLE_NET"
+        [ loadPlugin oauth2AzureAD "AZURE_AD"
+        , loadPlugin (oauth2BattleNet [whamlet|TODO|] "en") "BATTLE_NET"
         , loadPlugin oauth2Bitbucket "BITBUCKET"
         , loadPlugin (oauth2Eve Plain) "EVE_ONLINE"
         , loadPlugin oauth2GitHub "GITHUB"
@@ -142,10 +146,11 @@
         , loadPlugin oauth2Salesforce "SALES_FORCE"
         , loadPlugin oauth2Slack "SLACK"
         , loadPlugin (oauth2Spotify []) "SPOTIFY"
+        , loadPlugin oauth2WordPressDotCom "WORDPRESS_DOT_COM"
         , loadPlugin oauth2Upcase "UPCASE"
         ]
 
-    return App{..}
+    return App {..}
   where
     loadPlugin f prefix = do
         clientId <- getEnv $ prefix <> "_CLIENT_ID"
diff --git a/src/Yesod/Auth/OAuth2/Dispatch.hs b/src/Yesod/Auth/OAuth2/Dispatch.hs
--- a/src/Yesod/Auth/OAuth2/Dispatch.hs
+++ b/src/Yesod/Auth/OAuth2/Dispatch.hs
@@ -5,6 +5,7 @@
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeApplications #-}
 {-# LANGUAGE TypeFamilies #-}
 module Yesod.Auth.OAuth2.Dispatch
     ( FetchCreds
@@ -14,13 +15,14 @@
 
 import Control.Exception.Safe
 import Control.Monad (unless, (<=<))
-import Data.Monoid ((<>))
+import Crypto.Random (getRandomBytes)
+import Data.ByteArray.Encoding (Base(Base64), convertToBase)
+import Data.ByteString (ByteString)
 import Data.Text (Text)
 import qualified Data.Text as T
-import Data.Text.Encoding (encodeUtf8)
+import Data.Text.Encoding (decodeUtf8, encodeUtf8)
 import Network.HTTP.Conduit (Manager)
 import Network.OAuth.OAuth2
-import System.Random (newStdGen, randomRs)
 import URI.ByteString.Extension
 import Yesod.Auth hiding (ServerError)
 import Yesod.Auth.OAuth2.ErrorResponse
@@ -68,7 +70,7 @@
     code <- requireGetParam "code"
     manager <- authHttpManager
     oauth2' <- withCallbackAndState name oauth2 csrf
-    token <- errLeft $ fetchAccessToken manager oauth2' $ ExchangeToken code
+    token <- errLeft $ fetchAccessToken2 manager oauth2' $ ExchangeToken code
     creds <- errLeft $ tryFetchCreds $ getCreds manager token
     setCredsRedirect creds
   where
@@ -142,7 +144,9 @@
 setSessionCSRF sessionKey = do
     csrfToken <- liftIO randomToken
     csrfToken <$ setSession sessionKey csrfToken
-    where randomToken = T.pack . take 30 . randomRs ('a', 'z') <$> newStdGen
+  where
+    randomToken =
+        decodeUtf8 . convertToBase @ByteString Base64 <$> getRandomBytes 64
 
 -- | Verify the callback provided the same CSRF token as in our session
 verifySessionCSRF :: MonadHandler m => Text -> m Text
diff --git a/src/Yesod/Auth/OAuth2/Prelude.hs b/src/Yesod/Auth/OAuth2/Prelude.hs
--- a/src/Yesod/Auth/OAuth2/Prelude.hs
+++ b/src/Yesod/Auth/OAuth2/Prelude.hs
@@ -54,13 +54,13 @@
     -- * Temporary, until I finish re-structuring modules
     , authOAuth2
     , authOAuth2Widget
-    ) where
+    )
+where
 
 import Control.Exception.Safe
 import Data.Aeson
 import Data.ByteString (ByteString)
 import qualified Data.ByteString.Lazy as BL
-import Data.Semigroup ((<>))
 import Data.Text (Text)
 import qualified Data.Text as T
 import Data.Text.Encoding
diff --git a/src/Yesod/Auth/OAuth2/WordPressDotCom.hs b/src/Yesod/Auth/OAuth2/WordPressDotCom.hs
new file mode 100644
--- /dev/null
+++ b/src/Yesod/Auth/OAuth2/WordPressDotCom.hs
@@ -0,0 +1,48 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Yesod.Auth.OAuth2.WordPressDotCom
+    ( oauth2WordPressDotCom
+    )
+where
+
+import qualified Data.Text as T
+import Yesod.Auth.OAuth2.Prelude
+
+pluginName :: Text
+pluginName = "WordPress.com"
+
+newtype WpUser = WpUser Int
+
+instance FromJSON WpUser where
+    parseJSON = withObject "WpUser" $ \o -> WpUser <$> o .: "ID"
+
+oauth2WordPressDotCom
+    :: (YesodAuth m)
+    => Text -- ^ Client Id
+    -> Text -- ^ Client Secret
+    -> AuthPlugin m
+oauth2WordPressDotCom clientId clientSecret =
+    authOAuth2 pluginName oauth2 $ \manager token -> do
+        (WpUser userId, userResponse) <- authGetProfile
+            pluginName
+            manager
+            token
+            "https://public-api.wordpress.com/rest/v1/me/"
+
+        pure Creds
+            { credsPlugin = pluginName
+            , credsIdent = T.pack $ show userId
+            , credsExtra = setExtra token userResponse
+            }
+
+  where
+    oauth2 = OAuth2
+        { oauthClientId = clientId
+        , oauthClientSecret = clientSecret
+        , oauthOAuthorizeEndpoint =
+            "https://public-api.wordpress.com/oauth2/authorize"
+                `withQuery` [scopeParam "," ["auth"]]
+        , oauthAccessTokenEndpoint =
+            "https://public-api.wordpress.com/oauth2/token"
+        , oauthCallback = Nothing
+        }
diff --git a/yesod-auth-oauth2.cabal b/yesod-auth-oauth2.cabal
--- a/yesod-auth-oauth2.cabal
+++ b/yesod-auth-oauth2.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.31.2.
+-- This file has been generated from package.yaml by hpack version 0.33.0.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: e04edfe71067040f559a7ef9bdb8aef187060f21ee13314bbaaec9612a9c5c8d
+-- hash: a7a343fd632bb3c2411438ac0220b2a3c5071b5d28da37e807beedbcac6eca1f
 
 name:           yesod-auth-oauth2
-version:        0.6.1.2
+version:        0.6.1.3
 synopsis:       OAuth 2.0 authentication plugins
 description:    Library to authenticate with OAuth 2.0 for Yesod web applications.
 category:       Web
@@ -51,22 +51,24 @@
       Yesod.Auth.OAuth2.Slack
       Yesod.Auth.OAuth2.Spotify
       Yesod.Auth.OAuth2.Upcase
+      Yesod.Auth.OAuth2.WordPressDotCom
   other-modules:
       Paths_yesod_auth_oauth2
   hs-source-dirs:
       src
   ghc-options: -Wall
   build-depends:
-      aeson >=0.6 && <1.5
+      aeson >=0.6 && <1.6
     , base >=4.9.0.0 && <5
     , bytestring >=0.9.1.4
+    , cryptonite
     , errors
-    , hoauth2 >=1.3.0 && <1.9
+    , hoauth2 >=1.7.0 && <1.15
     , http-client >=0.4.0 && <0.7
     , http-conduit >=2.0 && <3.0
     , http-types >=0.8 && <0.13
+    , memory
     , microlens
-    , random
     , safe-exceptions
     , text >=0.7 && <2.0
     , uri-bytestring
