diff --git a/happstack-server.cabal b/happstack-server.cabal
--- a/happstack-server.cabal
+++ b/happstack-server.cabal
@@ -1,5 +1,5 @@
 Name:                happstack-server
-Version:             7.7.1.2
+Version:             7.7.2
 Synopsis:            Web related tools and services.
 Description:         Happstack Server provides an HTTP server and a rich set of functions for routing requests, handling query parameters, generating responses, working with cookies, serving files, and more. For in-depth documentation see the Happstack Crash Course <http://happstack.com/docs/crashcourse/index.html>
 License:             BSD3
@@ -86,7 +86,7 @@
                        sendfile               >= 0.7.1 && < 0.8,
                        system-filepath        >= 0.3.1,
                        syb,
-                       text                   >= 0.10  && < 1.3,
+                       text                   >= 0.10  && < 2.1,
                        time,
                        threads                >= 0.5,
                        transformers           >= 0.1.3 && < 0.7,
diff --git a/src/Happstack/Server/Auth.hs b/src/Happstack/Server/Auth.hs
--- a/src/Happstack/Server/Auth.hs
+++ b/src/Happstack/Server/Auth.hs
@@ -2,8 +2,12 @@
 -- | Support for basic access authentication <http://en.wikipedia.org/wiki/Basic_access_authentication>
 module Happstack.Server.Auth where
 
+import Data.Foldable (foldl')
+import Data.Bits (xor, (.|.))
+import Data.Maybe (fromMaybe)
 import Control.Monad                             (MonadPlus(mzero, mplus))
 import Data.ByteString.Base64                    as Base64
+import qualified Data.ByteString                 as BS
 import qualified Data.ByteString.Char8           as B
 import qualified Data.Map                        as M
 import Happstack.Server.Monads                   (Happstack, escape, getHeaderM, setHeaderM)
@@ -72,9 +76,28 @@
 
 -- | Function that looks up the plain text password for username in a
 -- Map and returns True if it matches with the given password.
+--
+-- Note: The implementation is hardened against timing attacks but not
+-- completely safe. Ideally you should build your own predicate, using
+-- a robust constant-time equality comparison from a cryptographic
+-- library like sodium.
 validLoginPlaintext ::
   M.Map String String -- ^ the username password map
   -> B.ByteString -- ^ the username
   -> B.ByteString -- ^ the password
   -> Bool
-validLoginPlaintext authMap name password = M.lookup (B.unpack name) authMap == Just (B.unpack password)
+validLoginPlaintext authMap name password = fromMaybe False $ do
+    r <- M.lookup (B.unpack name) authMap
+    pure (constTimeEq (B.pack r) password)
+  where
+    -- (Mostly) constant time equality of bytestrings to prevent timing attacks by testing out passwords. This still
+    -- allows to extract the length of the configured password via timing attacks. This implementation is still brittle
+    -- in the sense that it relies on GHC not unrolling or vectorizing the loop.
+    {-# NOINLINE constTimeEq #-}
+    constTimeEq :: BS.ByteString -> BS.ByteString -> Bool
+    constTimeEq x y
+      | BS.length x /= BS.length y
+      = False
+
+      | otherwise
+      = foldl' (.|.) 0 (BS.zipWith xor x y) == 0
