blog-banner

Regenerate a Missing Form #Token

  • Drupal 6
  • Drupal Planet
  • Form API

It may be a weird case for having to regenerate $form['#token'] and $form['form_token'] in Drupal form API manually. But we had a use case where the same form is presented to the user first as an anonymous user and later as an authenticated user.

The Anonymous version of the form fails CSRF validation if $form['#token'] or $form['form_token'] is set and it's the other way around for authenticated user's form, requiring a valid acceptable value for the token. Our form's hook_validate() function does a background user registration in case the email ID is found to be valid. If other form fields are having validation errors, we have to present the same form filled to the user - but now with an authenticated user session and a valid form token.

A quick look at form.inc helps us in arriving at the code to use to regenerate token:

$form['#token'] = $form['form_id']['#value'];
$form['form_token'] = array(
    '#id' => form_clean_id('edit-'. $form['form_id']['#value'] .'-form-token'),
    '#type' => 'token',
    '#name' => 'form_token',
    '#value' => drupal_get_token($form['#token']),
);

However, the problem is where do we place the code? The source $form callback function may not be a suitable location because that would be too late to avoid the anonymous form submission from being successful or too early for the first appearance of the form on authenticated session not to have the token. Finally, we ended up placing the above code in template_preprocess() function. We used a global variable to indicate the template function when to add the form token. The conditional checks in the template_preprocess function are as follows:

if ($GLOBALS['registration_done_in_hook_validate'] === TRUE && !$form['form_token']) {

    // code to regenerate form_token

}

 

Get awesome tech content in your inbox