Drupal Token Validation


On web security we need to be two steps ahead, then if we expose any resource or path we should not trust that any request is coming from our page. Drupal implements token validation to achieve that, on this page we walk through on a simple example about how do that.

Basically we should use two functions that Drupal provides us,

If you want to download full project, it is available from Github.

Create custom module

In this case we need to create a custom module named: "utilities" at first step we will create a constant to be available on our module, just like this:

/**
 * Define secret token value.
 */ 
define('TOKEN_VALUE', 'SomeSecretTokenValue');

Create new path

Now we will implement a new path by using "hook_menu" where we will define a full access through "access page" option as true.

/**
 * Implements hook_menu().
 */ 
function utilities_menu() { 
	// Secret page definition.
	$items['secret'] = array(
		'title' => 'Secret page',
		'description' => t('Valid Drupal token from query string.'),
		'page callback' => 'utilities_secret_page_callback',
		'access callback' => TRUE,
	);
	return $items;
}

Right after define this new path we go to create our page callback function where we only print a random string value, of course, we go to check if a token value comes from query string and if it is valid as well.

/**
 * Callback page menu to render secret page.
 */ 
function utilities_secret_page_callback() { 
	// Retrieve all query string. 
	$parameters = drupal_get_query_parameters(); 
	// Check if token is already defined. 
	if (empty($parameters['token'])) { 
		// Otherwise denied access to page. 
		utilities_denied_access('Token missing.');
	} 
	// Then check if current toke value is valid.
	if (!drupal_valid_token($parameters['token'], TOKEN_VALUE)) {
		// Otherwise denied access to page.
		utilities_denied_access('Token is not valid.');
	} 
	// Define secret page output.
	$output['secret_page'] = array(
		'#theme' => 'html_tag',
		'#tag' => 'div',
		'#value' => 'Unique ID: ' . uniqid(),
	); 
	return $output;
}

We create a helper function named: "utilities_denied_access()" what it receives a string parameter to show an error message and denied access to our custom page.

/**
 * Helper function to denied access to page and show error message.
 *
 * @param string $message Given message to show.
 */ 
function utilities_denied_access($message) { 
  $message = t($message); 
  drupal_set_message($message, 'error');
  drupal_access_denied(); 
}

Set Drupal token

Since one parameter to build a Drupal token is current session id, we need to set up this value before Drupal render the page, there are bunch of ways where we could nail it, however we just go to implement "hook_preprocess_HOOK()" to overwrite the menu link

/**
 * Implements hook_preprocess_HOOK().
  */ 
function utilities_preprocess_menu_link(&$variables) { 
	// Check current element's href attribute.
	if (!empty($variables['element']) && $variables['element']['#href'] == 'secret') {
		// Build query string with token and its current value.
		$query_string = array(
			'token' => drupal_get_token(TOKEN_VALUE),
		);
		// Add query options to element.
		$variables['element']['#localized_options'] = array(
			'query' => $query_string,
		);
	}
}

This should be good enough to append token value as query string to link before it gets render on page.

Once we click to this link, it will redirect to our custom page then the Drupal token we appended as query string will allows access there.