Merge pull request #1446 from bigs/extensible-password-hashing

Extend `YesodAuthEmail` to support extensible password hashing
This commit is contained in:
Sibi 2017-10-01 22:31:16 +05:30 committed by GitHub
commit 299d0569af
3 changed files with 42 additions and 17 deletions

View File

@ -1,3 +1,8 @@
## 1.4.20
* Extend `YesodAuthEmail` to support extensible password hashing via
`hashAndSaltPassword` and `verifyPassword` functions
## 1.4.19 ## 1.4.19
* Adjust English localization to distinguish between "log in" (verb) and "login" (noun) * Adjust English localization to distinguish between "log in" (verb) and "login" (noun)

View File

@ -4,7 +4,7 @@
{-# LANGUAGE PatternGuards #-} {-# LANGUAGE PatternGuards #-}
{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE Rank2Types #-} {-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables#-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
-- | A Yesod plugin for Authentication via e-mail -- | A Yesod plugin for Authentication via e-mail
-- --
@ -132,7 +132,7 @@ import Safe (readMay)
import System.IO.Unsafe (unsafePerformIO) import System.IO.Unsafe (unsafePerformIO)
import qualified Text.Email.Validate import qualified Text.Email.Validate
import Data.Aeson.Types (Parser, Result(..), parseMaybe, withObject, (.:?)) import Data.Aeson.Types (Parser, Result(..), parseMaybe, withObject, (.:?))
import Data.Maybe (isJust, isNothing, fromJust) import Data.Maybe (isJust)
import Data.ByteArray (convert) import Data.ByteArray (convert)
loginR, registerR, forgotPasswordR, setpassR :: AuthRoute loginR, registerR, forgotPasswordR, setpassR :: AuthRoute
@ -203,6 +203,22 @@ class ( YesodAuth site
-- @since 1.1.0 -- @since 1.1.0
setVerifyKey :: AuthEmailId site -> VerKey -> HandlerT site IO () setVerifyKey :: AuthEmailId site -> VerKey -> HandlerT site IO ()
-- | Hash and salt a password
--
-- Default: 'saltPass'.
--
-- @since 1.4.20
hashAndSaltPassword :: Text -> HandlerT site IO SaltedPass
hashAndSaltPassword = liftIO . saltPass
-- | Verify a password matches the stored password for the given account.
--
-- Default: Fetch a password with 'getPassword' and match using 'Yesod.Auth.Util.PasswordStore.verifyPassword'.
--
-- @since 1.4.20
verifyPassword :: Text -> SaltedPass -> HandlerT site IO Bool
verifyPassword plain salted = return $ isValidPass plain salted
-- | Verify the email address on the given account. -- | Verify the email address on the given account.
-- --
-- __/Warning!/__ If you have persisted the @'AuthEmailId' site@ -- __/Warning!/__ If you have persisted the @'AuthEmailId' site@
@ -620,12 +636,14 @@ postLoginR = do
, emailCredsStatus <$> mecreds , emailCredsStatus <$> mecreds
) of ) of
(Just aid, Just email', Just True) -> do (Just aid, Just email', Just True) -> do
mrealpass <- lift $ getPassword aid mrealpass <- lift $ getPassword aid
case mrealpass of case mrealpass of
Nothing -> return Nothing Nothing -> return Nothing
Just realpass -> return $ if isValidPass pass realpass Just realpass -> do
then Just email' passValid <- lift $ verifyPassword pass realpass
else Nothing return $ if passValid
then Just email'
else Nothing
_ -> return Nothing _ -> return Nothing
let isEmail = Text.Email.Validate.isValid $ encodeUtf8 identifier let isEmail = Text.Email.Validate.isValid $ encodeUtf8 identifier
case maid of case maid of
@ -753,14 +771,16 @@ postPasswordR = do
then getThird jcreds then getThird jcreds
else fcurrent else fcurrent
mrealpass <- lift $ getPassword aid mrealpass <- lift $ getPassword aid
case mrealpass of case (mrealpass, current) of
Nothing -> (Nothing, _) ->
lift $ loginErrorMessage (tm setpassR) "You do not currently have a password set on your account" lift $ loginErrorMessage (tm setpassR) "You do not currently have a password set on your account"
Just realpass (_, Nothing) ->
| isNothing current -> loginErrorMessageI LoginR Msg.BadSetPass loginErrorMessageI LoginR Msg.BadSetPass
| isValidPass (fromJust current) realpass -> confirmPassword aid tm jcreds (Just realpass, Just current') -> do
| otherwise -> passValid <- lift $ verifyPassword current' realpass
lift $ loginErrorMessage (tm setpassR) "Invalid current password, please try again" if passValid
then confirmPassword aid tm jcreds
else lift $ loginErrorMessage (tm setpassR) "Invalid current password, please try again"
where where
msgOk = Msg.PassUpdated msgOk = Msg.PassUpdated
@ -787,7 +807,7 @@ postPasswordR = do
case isSecure of case isSecure of
Left e -> lift $ loginErrorMessage (tm setpassR) e Left e -> lift $ loginErrorMessage (tm setpassR) e
Right () -> do Right () -> do
salted <- liftIO $ saltPass new salted <- lift $ hashAndSaltPassword new
y <- lift $ do y <- lift $ do
setPassword aid salted setPassword aid salted
deleteSession loginLinkKey deleteSession loginLinkKey

View File

@ -1,5 +1,5 @@
name: yesod-auth name: yesod-auth
version: 1.4.19 version: 1.4.20
license: MIT license: MIT
license-file: LICENSE license-file: LICENSE
author: Michael Snoyman, Patrick Brisbin author: Michael Snoyman, Patrick Brisbin