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.
This commit is contained in:
patrick brisbin 2020-08-19 11:51:45 -04:00
parent e46da4cafb
commit cd3875b797
2 changed files with 10 additions and 4 deletions

View File

@ -24,13 +24,14 @@ library:
dependencies: dependencies:
- aeson >=0.6 && <1.6 - aeson >=0.6 && <1.6
- bytestring >=0.9.1.4 - bytestring >=0.9.1.4
- cryptonite
- errors - errors
- hoauth2 >=1.7.0 && <1.15 - hoauth2 >=1.7.0 && <1.15
- http-client >=0.4.0 && <0.7 - http-client >=0.4.0 && <0.7
- http-conduit >=2.0 && <3.0 - http-conduit >=2.0 && <3.0
- http-types >=0.8 && <0.13 - http-types >=0.8 && <0.13
- memory
- microlens - microlens
- random
- safe-exceptions - safe-exceptions
- text >=0.7 && <2.0 - text >=0.7 && <2.0
- uri-bytestring - uri-bytestring

View File

@ -5,6 +5,7 @@
{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
module Yesod.Auth.OAuth2.Dispatch module Yesod.Auth.OAuth2.Dispatch
( FetchCreds ( FetchCreds
@ -14,12 +15,14 @@ where
import Control.Exception.Safe import Control.Exception.Safe
import Control.Monad (unless, (<=<)) import Control.Monad (unless, (<=<))
import Crypto.Random (getRandomBytes)
import Data.ByteArray.Encoding (Base(Base64), convertToBase)
import Data.ByteString (ByteString)
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as T import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8) import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Network.HTTP.Conduit (Manager) import Network.HTTP.Conduit (Manager)
import Network.OAuth.OAuth2 import Network.OAuth.OAuth2
import System.Random (newStdGen, randomRs)
import URI.ByteString.Extension import URI.ByteString.Extension
import Yesod.Auth hiding (ServerError) import Yesod.Auth hiding (ServerError)
import Yesod.Auth.OAuth2.ErrorResponse import Yesod.Auth.OAuth2.ErrorResponse
@ -141,7 +144,9 @@ setSessionCSRF :: MonadHandler m => Text -> m Text
setSessionCSRF sessionKey = do setSessionCSRF sessionKey = do
csrfToken <- liftIO randomToken csrfToken <- liftIO randomToken
csrfToken <$ setSession sessionKey csrfToken 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 -- | Verify the callback provided the same CSRF token as in our session
verifySessionCSRF :: MonadHandler m => Text -> m Text verifySessionCSRF :: MonadHandler m => Text -> m Text