diff --git a/include/class.csrf.php b/include/class.csrf.php
index 283aef53b361b6669d7e88503052530dd6fddef8..a1c3aed21392d5932b6b1edb31108cc6d3bedf8a 100644
--- a/include/class.csrf.php
+++ b/include/class.csrf.php
@@ -71,11 +71,7 @@ Class CSRF {
     }
 
     function validateToken($token) {
-        $rv = $token && trim($token)==$this->getToken() && !$this->isExpired();
-        // Prevent the token from being reused
-        if ($rv && !defined('AJAX_REQUEST'))
-            $this->rotate();
-        return $rv;
+        return ($token && trim($token)==$this->getToken() && !$this->isExpired());
     }
 
     function getFormInput($name='') {
diff --git a/login.php b/login.php
index a08c83a010f5828acbf9015f534a01e6361626c3..1b6973ce8537762d07a76c1d3db60013b6aa3a4d 100644
--- a/login.php
+++ b/login.php
@@ -32,6 +32,19 @@ else
 
 $suggest_pwreset = false;
 
+// Check the CSRF token, and ensure that future requests will have to use a
+// different CSRF token. This will help ward off both parallel and serial
+// brute force attacks, because new tokens will have to be requested for
+// each attempt.
+if ($_POST) {
+    // Check CSRF token
+    if (!$ost->checkCSRFToken())
+        Http::response(400, __('Valid CSRF Token Required'));
+
+    // Rotate the CSRF token (original cannot be reused)
+    $ost->getCSRF()->rotate();
+}
+
 if ($_POST && isset($_POST['luser'])) {
     if (!$_POST['luser'])
         $errors['err'] = __('Valid username or email address is required');