Skip to main content
knackforge blog knowledge base

Regenerate a missing form #token

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.

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 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 is as follows:

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

    // code to regenerate form_token

}