title: Yesod.Auth.Email setting password always returns "Passwords did not match, please try again"
body: <p>Currently trying to set up <code>Yesod.Auth.Email</code>, but running into a bit of a problem after getting the verification url. </p>
  
  <p>On the "Set password" page (with "New password" and "Confirm"), after entering the password and the same in the confirmation box, it always returns "Passwords did not match, please try again".</p>
  
  <p>This is the request that is logged,</p>
  
  <pre><code>POST /auth/page/email/set-password
    Params: [("_token","wcpv0LhJfy"),("new","1234"),("confirm","1234")]
    Request Body: _token=wcpv0LhJfy&amp;new=1234&amp;confirm=1234
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Status: 303 See Other 0.002459s
  </code></pre>
  
  <p>Showing that they should indeed match.</p>
  
  <p>Looking into the source code for the handler <a href="https://github.com/yesodweb/yesod/blob/b9ece6f2426a88c1a89be6b4bc9dddd6b2922dd8/yesod-auth/Yesod/Auth/Email.hs#L756" rel="nofollow noreferrer"><code>postPasswordR</code></a> it's not entirely clear to me why it fails, since this isn't something you overwrite in <code>instance YesodAuthEmail App</code>?</p>
  
  <h2>A Minimal Example</h2>
  
  <p>Taken straight from <a href="http://www.yesodweb.com/book/authentication-and-authorization#authentication-and-authorization_email" rel="nofollow noreferrer">the email-auth section in the Yesod book</a>, and saved as <code>Main.hs</code>,</p>
  
  <pre><code>{-# LANGUAGE DeriveDataTypeable #-}
  {-# LANGUAGE FlexibleContexts #-}
  {-# LANGUAGE GADTs #-}
  {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE QuasiQuotes #-}
  {-# LANGUAGE TemplateHaskell #-}
  {-# LANGUAGE TypeFamilies #-}
  
  import Control.Monad (join)
  import Control.Monad.Logger (runNoLoggingT)
  import Data.Maybe (isJust)
  import Data.Text (Text, unpack)
  import qualified Data.Text.Lazy.Encoding
  import Data.Typeable (Typeable)
  import Database.Persist.Sqlite
  import Database.Persist.TH
  import Network.Mail.Mime
  import Text.Blaze.Html.Renderer.Utf8 (renderHtml)
  import Text.Hamlet (shamlet)
  import Text.Shakespeare.Text (stext)
  import Yesod
  import Yesod.Auth
  import Yesod.Auth.Email
  
  share
    [ mkPersist
        sqlSettings
        { mpsGeneric = False
        }
    , mkMigrate "migrateAll"
    ]
    [persistLowerCase|
  User
      email Text
      password Text Maybe -- Password may not be set yet
      verkey Text Maybe -- Used for resetting passwords
      verified Bool
      UniqueUser email
      deriving Typeable
  |]
  
  data App =
    App SqlBackend
  
  mkYesod
    "App"
    [parseRoutes|
  / HomeR GET
  /auth AuthR Auth getAuth
  |]
  
  instance Yesod App
           -- Emails will include links, so be sure to include an approot so that
           -- the links are valid!
                                   where
    approot = ApprootStatic "http://localhost:3000"
  
  instance RenderMessage App FormMessage where
    renderMessage _ _ = defaultFormMessage
  
  -- Set up Persistent
  instance YesodPersist App where
    type YesodPersistBackend App = SqlBackend
    runDB f = do
      App conn &lt;- getYesod
      runSqlConn f conn
  
  instance YesodAuth App where
    type AuthId App = UserId
    loginDest _ = HomeR
    logoutDest _ = HomeR
    authPlugins _ = [authEmail]
    -- Need to find the UserId for the given email address.
    getAuthId creds =
      runDB $
      do x &lt;- insertBy $ User (credsIdent creds) Nothing Nothing False
         return $
           Just $
           case x of
             Left (Entity userid _) -&gt; userid -- newly added user
             Right userid -&gt; userid -- existing user
    authHttpManager = error "Email doesn't need an HTTP manager"
  
  instance YesodAuthPersist App
  
  -- Here's all of the email-specific code
  instance YesodAuthEmail App where
    type AuthEmailId App = UserId
    afterPasswordRoute _ = HomeR
    addUnverified email verkey =
      runDB $ insert $ User email Nothing (Just verkey) False
    sendVerifyEmail email _ verurl
                            -- Print out to the console the verification email, for easier
                            -- debugging.
     = do
      liftIO $ putStrLn $ "Copy/ Paste this URL in your browser:" ++ unpack verurl
      -- Send email.
      liftIO $
        renderSendMail
          (emptyMail $ Address Nothing "noreply")
          { mailTo = [Address Nothing email]
          , mailHeaders = [("Subject", "Verify your email address")]
          , mailParts = [[textPart, htmlPart]]
          }
      where
        textPart =
          Part
          { partType = "text/plain; charset=utf-8"
          , partEncoding = None
          , partFilename = Nothing
          , partContent =
            Data.Text.Lazy.Encoding.encodeUtf8
              [stext|
                      Please confirm your email address by clicking on the link below.
  
                      #{verurl}
  
                      Thank you
                  |]
          , partHeaders = []
          }
        htmlPart =
          Part
          { partType = "text/html; charset=utf-8"
          , partEncoding = None
          , partFilename = Nothing
          , partContent =
            renderHtml
              [shamlet|
                      &lt;p&gt;Please confirm your email address by clicking on the link below.
                      &lt;p&gt;
                          &lt;a href=#{verurl}&gt;#{verurl}
                      &lt;p&gt;Thank you
                  |]
          , partHeaders = []
          }
    getVerifyKey = runDB . fmap (join . fmap userVerkey) . get
    setVerifyKey uid key = runDB $ update uid [UserVerkey =. Just key]
    verifyAccount uid =
      runDB $
      do mu &lt;- get uid
         case mu of
           Nothing -&gt; return Nothing
           Just u -&gt; do
             update uid [UserVerified =. True]
             return $ Just uid
    getPassword = runDB . fmap (join . fmap userPassword) . get
    setPassword uid pass = runDB $ update uid [UserPassword =. Just pass]
    getEmailCreds email =
      runDB $
      do mu &lt;- getBy $ UniqueUser email
         case mu of
           Nothing -&gt; return Nothing
           Just (Entity uid u) -&gt;
             return $
             Just
               EmailCreds
               { emailCredsId = uid
               , emailCredsAuthId = Just uid
               , emailCredsStatus = isJust $ userPassword u
               , emailCredsVerkey = userVerkey u
               , emailCredsEmail = email
               }
    getEmail = runDB . fmap (fmap userEmail) . get
  
  getHomeR :: Handler Html
  getHomeR = do
    maid &lt;- maybeAuthId
    defaultLayout
      [whamlet|
              &lt;p&gt;Your current auth ID: #{show maid}
              $maybe _ &lt;- maid
                  &lt;p&gt;
                      &lt;a href=@{AuthR LogoutR}&gt;Logout
              $nothing
                  &lt;p&gt;
                      &lt;a href=@{AuthR LoginR}&gt;Go to the login page
          |]
  
  main :: IO ()
  main =
    runNoLoggingT $
    withSqliteConn "email.db3" $
    \conn -&gt;
       liftIO $
       do runSqlConn (runMigration migrateAll) conn
          warp 3000 $ App conn
  </code></pre>
  
  <p>It is then run with <code>stack runghc Main.hs</code> after having installed <code>stack install yesod persistent-sqlite</code>. </p>
  
  <p>My stackage LTS version is <code>lts-7.14</code>, and I'm running GHC version <code>8.0.1.20161117</code>.</p>
  
  <p>Still getting the same result.</p>