diff --git a/includes/form.inc b/includes/form.inc
index 8ae8065..2d81b95 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -530,7 +530,7 @@ function form_set_cache($form_build_id, $form, $form_state) {
 
   // Cache form structure.
   if (isset($form)) {
-    if ($GLOBALS['user']->uid) {
+    if ($GLOBALS['user']->uid && empty($form_state['no_cache_token'])) {
       $form['#cache_token'] = drupal_get_token();
     }
     cache_set('form_' . $form_build_id, $form, 'cache_form', REQUEST_TIME + $expire);
diff --git a/modules/user/tests/user_ajax_test.info b/modules/user/tests/user_ajax_test.info
new file mode 100644
index 0000000..4798ea3
--- /dev/null
+++ b/modules/user/tests/user_ajax_test.info
@@ -0,0 +1,6 @@
+name = "User module ajax tests"
+description = "Support module for user ajax testing."
+package = Testing
+version = VERSION
+core = 7.x
+hidden = TRUE
diff --git a/modules/user/tests/user_ajax_test.module b/modules/user/tests/user_ajax_test.module
new file mode 100644
index 0000000..87eb37c
--- /dev/null
+++ b/modules/user/tests/user_ajax_test.module
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Dummy module to use AJAX for login forms.
+ */
+
+/**
+ * Implements hook_form_alter().
+ */
+function user_ajax_test_form_alter(&$form, &$form_state, $form_id) {
+  if (in_array($form_id, array('user_login', 'user_login_block'))) {
+    // Add a name for xpath to find.
+    $form['actions']['submit']['#name'] = 'submit';
+
+    // Turn it into an AJAX element.
+    $form['actions']['submit']['#ajax'] = array(
+      'wrapper' => $form['#id'],
+      'callback' => 'user_ajax_test_form_user_login_ajax',
+      'progress' => array(
+        'type' => 'throbber',
+        'message' => t('Logging in'),
+      ),
+      'event' => 'click',
+    );
+  }
+}
+
+/**
+ * AJAX Callback for user_login_form().
+ *
+ * @see ajax_login_test_form_user_login_alter().
+ */
+function user_ajax_test_form_user_login_ajax($form, $form_state) {
+  global $user;
+  if ($user->uid) {
+    return t('Successfully logged in.');
+  }
+  else {
+    return $form;
+  }
+}
diff --git a/modules/user/user.module b/modules/user/user.module
index bff6f76..a2a95ef 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -2268,6 +2268,8 @@ function user_login_submit($form, &$form_state) {
   global $user;
   $user = user_load($form_state['uid']);
   $form_state['redirect'] = 'user/' . $user->uid;
+  // Prevent an un-wanted form cache token.
+  $form_state['no_cache_token'] = TRUE;
 
   user_login_finalize($form_state);
 }
diff --git a/modules/user/user.test b/modules/user/user.test
index 26e93ed..4bacc22 100644
--- a/modules/user/user.test
+++ b/modules/user/user.test
@@ -2346,3 +2346,105 @@ class UserValidateCurrentPassCustomForm extends DrupalWebTestCase {
     $this->assertText(t('The password has been validated and the form submitted successfully.'));
   }
 }
+
+/**
+ * Tests the user login forms work with caching and AJAX submits.
+ */
+class UserLoginAjaxCacheTestCase extends AJAXTestCase {
+
+  /**
+   * Provide information about the test.
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'User cached AJAX login',
+      'description' => 'Ensure that AJAX login forms continue to work with anonymous caching enabled.',
+      'group' => 'User',
+    );
+  }
+
+  /**
+   * Overrides DrupalWebTestCase::setUp().
+   */
+  public function setUp() {
+    parent::setUp('user_ajax_test');
+    variable_set('cache', 1);
+  }
+
+  /**
+   * Test that the user_login form cache works with AJAX submission.
+   */
+  public function testUserLoginForm() {
+    // Create a user.
+    $user = $this->drupalCreateUser();
+    $edit = array();
+    $edit['name'] = $user->name;
+    $edit['pass'] = $user->pass_raw;
+
+    // Log in using the page.
+    $commands = $this->drupalPostAJAX('user', $edit, array('submit' => t('Log in')));
+    if (empty($commands)) {
+      $this->fail(t('No valid response for first log in with user_login form.'));
+    }
+    else {
+      $expected = array(
+        'command' => 'insert',
+        'data' => t('Successfully logged in.'),
+      );
+      $this->assertCommand($commands, $expected, t('Successful first log in with user_login form.'));
+    }
+
+    // Now, log out and repeat.
+    $this->drupalLogout();
+    $commands = $this->drupalPostAJAX('user', $edit, array('submit' => t('Log in')));
+    if (empty($commands)) {
+      $this->fail(t('No valid response for second log in with user_login form.'));
+    }
+    else {
+      $expected = array(
+        'command' => 'insert',
+        'data' => t('Successfully logged in.'),
+      );
+      $this->assertCommand($commands, $expected, t('Successful second log in with user_login form.'));
+    }
+  }
+
+  /**
+   * Test that the user_login_block form cache works with AJAX submission.
+   */
+  public function testUserLoginBlockForm() {
+    // Create a user.
+    $user = $this->drupalCreateUser();
+    $edit = array();
+    $edit['name'] = $user->name;
+    $edit['pass'] = $user->pass_raw;
+
+    // Log in using the page.
+    $commands = $this->drupalPostAJAX('', $edit, array('submit' => t('Log in')));
+    if (empty($commands)) {
+      $this->fail(t('No valid response for first log in with user_login_block form.'));
+    }
+    else {
+      $expected = array(
+        'command' => 'insert',
+        'data' => t('Successfully logged in.'),
+      );
+      $this->assertCommand($commands, $expected, t('Successful first log in with user_login_block form.'));
+    }
+
+    // Now, log out and repeat.
+    $this->drupalLogout();
+    $commands = $this->drupalPostAJAX('', $edit, array('submit' => t('Log in')));
+    if (empty($commands)) {
+      $this->fail(t('No valid response for second log in with user_login_block form.'));
+    }
+    else {
+      $expected = array(
+        'command' => 'insert',
+        'data' => t('Successfully logged in.'),
+      );
+      $this->assertCommand($commands, $expected, t('Successful second log in with user_login_block form.'));
+    }
+  }
+
+}
