From cd3875b797e91cb357fc42fcfe57eb685f2622fe Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Wed, 19 Aug 2020 11:51:45 -0400 Subject: [PATCH] Strengthen random state token generation Previously: - System.Random, which seeds from system time (possible attack) - 30 characters, a-z (low entropy) Now: - Crypto.Random, accepted as "cryptographically secure" - 64 random bytes, Base64-encoded cryptonite was already a transitive dependency, so there is really no downside to this. Fixes #132. --- package.yaml | 3 ++- src/Yesod/Auth/OAuth2/Dispatch.hs | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/package.yaml b/package.yaml index 7647e82..e86f499 100644 --- a/package.yaml +++ b/package.yaml @@ -24,13 +24,14 @@ library: dependencies: - aeson >=0.6 && <1.6 - bytestring >=0.9.1.4 + - cryptonite - errors - 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 diff --git a/src/Yesod/Auth/OAuth2/Dispatch.hs b/src/Yesod/Auth/OAuth2/Dispatch.hs index 9011758..6cb17fa 100644 --- 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,12 +15,14 @@ where import Control.Exception.Safe import Control.Monad (unless, (<=<)) +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 @@ -141,7 +144,9 @@ setSessionCSRF :: MonadHandler m => Text -> m Text 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