How to add a form_token to a login form For security purposes, I need to add a form_token to the login form. However, when (in hook_form_alter) I use the same code Drupal uses in form.inc for other forms, the validation fails because the token calculated during validation is different from the one calculated originally.

The code I'm using is:

if (!isset($form['#token'])) {
  $form['#token'] = $form_id;
  $form['form_token'] = array(
    '#id' =&gt; drupal_html_id('edit-' . $form_id . '-form-token'),
    '#type' =&gt; 'token',
    '#default_value' =&gt; drupal_get_token($form['#token']),
    // Form processing and validation requires this value, so ensure the
    // submitted form value appears literally, regardless of custom #tree
    // and #parents being set elsewhere.
    '#parents' =&gt; array('form_token'),
  );
}


I'm calling the form with drupal_render(drupal_get_form('user_login')). I'm aware that Drupal is not using the form_token on the login page because it is often cached, but I have disabled the cache for that page in hook_init with: 

$GLOBALS['conf']['cache'] = FALSE 


How can I add and validate a form_token in the login form? I'm using Drupal 7.

Some extra info as to why I need this. The request to secure login forms against CSRF came up during a security scan and although I do not agree with the explanation for the request (easier to setup a brute force attack, despite auto blocking logins in such cases), there is a good explanation on stackoverflow as to why this still can be a good idea: Do login forms need tokens against CSRF attacks?
I ended up (as suggested) adding a token to all unsecured forms with hook_form_alter.

Seemed efficient to use drupal_get_token() for this, but that did not work because the session ID (used by drupal_get_token() to generate a token) alters when an (anonymous) user logs in. 

I therefore stored the first session id (when displaying the login page) in $_SESSION so I could retrieve it when validating. But putting something in $_SESSION apparently prevents Drupal from regenerating the session_id. And now that the session id is preserved during login, drupal_valid_token() also works as expected so I did not have to write a special token validation function.

This is the code I ended up with:

function MY_MODULE_form_alter(&amp;$form, $form_state, $form_id) {
    // add a custom csrf token for forms that do not have one
    if ($!isset($form['#token'])) {
        $form['anon_token'] = array(
            '#type' =&gt; 'token',
            '#default_value' =&gt; drupal_get_token()
        );

        $form['#validate'][] = 'MY_MODULE_validate_anon_token';

        // store current session id
        // touching $_SESSION alone seems to preserve the session id after login
        $sess_id = session_id();
        if (isset($_SESSION))
            $_SESSION['anon_session_id'] = $sess_id;
        else
            $_SESSION = array('anon_session_id' =&gt; $sess_id);
    }
}

function MY_MODULE_validate_anon_token($form, &amp;$form_state) {
    $token = '';
    if (isset($form_state['values']['anon_token']))
        $token = $form_state['values']['anon_token'];

    if (!drupal_valid_token($token)) {
        // not a valid token!
        $path = current_path();
        $query = drupal_get_query_parameters();
        $url = url($path, array('query' =&gt; $query));

        // Setting this error will cause the form to fail validation.
        form_set_error('form_token', t('The form has become outdated. Copy any unsaved work in the form below and then &lt;a href="@link"&gt;reload this page&lt;/a&gt;.', array('@link' =&gt; $url)));
    }
}