You are here

tokenauth.module in Token authentication 5

Same filename and directory in other branches
  1. 6.2 tokenauth.module
  2. 6 tokenauth.module
  3. 7 tokenauth.module

File

tokenauth.module
View source
<?php

/**
 * Implementation of hook_perm().
 */
function tokenauth_perm() {
  return array(
    'access tokenauth',
    'administer tokenauth',
  );
}

/**
 * Implementation of hook_settings().
 */
function tokenauth_admin_settings() {
  $form['tokenauth_general'] = array(
    '#type' => 'fieldset',
    '#title' => t('Token settings'),
  );
  $form['tokenauth_general']['tokenauth_length'] = array(
    '#type' => 'textfield',
    '#title' => t('Token length'),
    '#size' => 4,
    '#maxlength' => 4,
    '#required' => TRUE,
    '#default_value' => variable_get('tokenauth_length', 10),
    '#description' => t('Does not affect existing tokens.'),
  );
  $form['tokenauth_general']['tokenauth_pages'] = array(
    '#type' => 'textarea',
    '#title' => t('Activate Tokens on specific pages'),
    '#default_value' => variable_get('tokenauth_pages', "rss.xml\n*/feed\n*/opml"),
    '#description' => t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array(
      '%blog' => 'blog',
      '%blog-wildcard' => 'blog/*',
      '%front' => '<front>',
    )),
  );
  $form['tokenauth_advanced'] = array(
    '#type' => 'fieldset',
    '#title' => t('Token actions'),
    '#description' => t('Reset the tokens for all users. If you have changed token length, be sure to save that change before resetting all tokens.'),
  );
  $form['tokenauth_advanced']['tokenauth_reset'] = array(
    '#type' => 'submit',
    '#value' => t('Reset tokens'),
  );
  return system_settings_form($form);
}

/**
 * Implementation of hook_menu().
 */
function tokenauth_menu($may_cache) {
  global $user;
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/settings/tokenauth',
      'title' => t('Token authentication'),
      'description' => t('Configure length of tokens, specify which pages accept authentication via token, and reset all tokens, etc.'),
      'callback' => 'drupal_get_form',
      'callback arguments' => 'tokenauth_admin_settings',
      'access' => user_access('administer tokenauth'),
    );
    $items[] = array(
      'path' => 'admin/settings/tokenauth/reset',
      'title' => t('Reset tokens'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'tokenauth_reset_confirm',
      ),
      'access' => user_access('administer tokenauth'),
      'type' => MENU_CALLBACK,
    );
  }
  else {
    if (arg(0) == 'user' && is_numeric(arg(1))) {
      $items[] = array(
        'path' => 'user/' . arg(1) . '/tokenauth',
        'title' => t('Token auth'),
        'callback' => 'drupal_get_form',
        'callback arguments' => array(
          'tokenauth_user_profile_form',
          arg(1),
        ),
        'access' => (user_access('administer users') || $user->uid == arg(1)) && user_access('access tokenauth'),
        'type' => MENU_IS_LOCAL_TASK,
      );
      $items[] = array(
        'path' => 'user/' . arg(1) . '/tokenauth/reset',
        'title' => t('Reset token'),
        'callback' => 'drupal_get_form',
        'callback arguments' => array(
          'tokenauth_user_reset_confirm',
        ),
        'access' => (user_access('administer users') || $user->uid == arg(1)) && user_access('access tokenauth'),
        'type' => MENU_CALLBACK,
      );
    }
  }
  return $items;
}

/**
 * API function for retrieving the token for a given user.
 *
 * @param string $uid 
 *  Assumes current user if no user is provided.
 * @return string
 *  A token, or FALSE if user has no token.
 */
function tokenauth_get_token($uid = NULL) {
  if (is_null($uid)) {
    global $user;
    $uid = $user->uid;
  }
  $token = db_result(db_query("SELECT tt.token FROM {tokenauth_tokens} tt WHERE tt.uid = %d", $uid));
  if ($token) {
    return "token={$token}";
  }
  else {
    return FALSE;
  }
}

/**
 * Validate callback.
 */
function tokenauth_admin_settings_validate($form_id, $form_values) {
  if ($form_values['op'] == t('Reset tokens')) {
    drupal_goto('admin/settings/tokenauth/reset');
  }
  if ($form_values['tokenauth_length'] > 33) {
    form_set_error('tokenauth_length', t('The maximum token length is 32.'));
  }
}

/**
 * Menu callback: confirm reset tokens.
 */
function tokenauth_reset_confirm() {
  return confirm_form(array(), t('Are you sure you want to reset all tokens?'), 'admin/settings/tokenauth', t('After the tokens has been reset all users who use tokenised URLs will have to update them. This action cannot be undone.'), t('Reset tokens'), t('Cancel'));
}

/**
 * Handler for reset tokens confirmation
 */
function tokenauth_reset_confirm_submit($form_id, &$form) {
  if ($form['confirm']) {
    tokenauth_reset();
    drupal_set_message(t('All tokens have been reset.'));
    return 'admin/settings/tokenauth';
  }
}

/**
 * Reset all tokens.
 */
function tokenauth_reset() {
  $length = variable_get('tokenauth_length', 10);
  $sql = 'SELECT uid FROM {users} WHERE uid > 0';
  $result = db_query($sql);
  while ($row = db_fetch_object($result)) {
    $sql = "UPDATE {tokenauth_tokens} SET token = '%s' WHERE uid = %d";
    db_query($sql, user_password($length), $row->uid);
  }
}

/**
 * Menu callback: confirm reset  users token.
 */
function tokenauth_user_reset_confirm() {
  global $user;
  return confirm_form(array(), t('Are you sure you want to reset your token?'), "user/{$user->uid}/tokenauth", t('After the token has been reset all your tokenised URLs will have to be updated. This action cannot be undone.'), t('Reset token'), t('Cancel'));
}

/**
 * Handler for reset tokens confirmation
 */
function tokenauth_user_reset_confirm_submit($form_id, &$form) {
  global $user;
  if ($form['confirm']) {
    tokenauth_user_reset();
    drupal_set_message(t('The token have been reset.'));
    return "user/{$user->uid}/tokenauth";
  }
}

/**
 * Reset a users token.
 */
function tokenauth_user_reset() {
  global $user;
  $length = variable_get('tokenauth_length', 10);
  $sql = "UPDATE {tokenauth_tokens} SET token = '%s' WHERE uid = %d";
  db_query($sql, user_password($length), $user->uid);
}

/**
 * Menu callback. Prints the token and instructions.
 */
function tokenauth_user_profile_form($uid) {
  if ($account = user_load(array(
    'uid' => (int) $uid,
  ))) {
    drupal_set_title($account->name);
    $token = tokenauth_get_token($account->uid);
    $output = t('To enable aggregators, feed readers and other simple clients to see restricted content on this site you may use an authentication token. The token is unique and tied to your account so keep it private. ');
    $output .= t('Simply append this querystring to any feed on this site. Some links may already have added this for you.') . '<br />';
    $output .= '<code>' . check_plain("?token={$token}") . '</code><br /><br />';
    $output .= t('Here are some example links to get you started:');
    $items = array();
    $items[] = l(t('Front page'), 'rss.xml', array(
      'title' => url('rss.xml', "token={$token}", NULL, TRUE),
    ), "token={$token}", NULL, FALSE, TRUE);
    $items[] = l(t('Blog'), 'blog/feed', array(
      'title' => url('blog/feed', "token={$token}", NULL, TRUE),
    ), "token={$token}", NULL, FALSE, TRUE);
    $output .= theme('item_list', $items);
    $form['preamble'] = array(
      '#value' => $output,
    );
    $form['uid'] = array(
      '#type' => 'value',
      '#value' => $uid,
    );
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Reset token'),
    );
    return $form;
  }
}
function tokenauth_user_profile_form_submit($form_id, $form_values) {
  return 'user/' . $form_values['uid'] . '/tokenauth/reset';
}

/**
 * Implementation of hook_init().
 */
function tokenauth_init() {
  global $user;

  // Process any provided token and log in user
  if (!$user->uid && $_REQUEST['token'] && tokenauth_allowed_pages($_GET['q']) && function_exists('drupal_set_content')) {
    $sql = "SELECT tt.uid FROM {tokenauth_tokens} tt INNER JOIN {users} u ON tt.uid = u.uid WHERE token = '%s' AND u.status != 0";
    if ($uid = db_result(db_query($sql, $_REQUEST['token']))) {
      $user = user_load(array(
        'uid' => $uid,
      ));
      $_SESSION['tokenauth_auth'] = TRUE;

      // Just store the fact that this user authenticated via token
    }
    else {

      // Supplied an invalid token
      drupal_access_denied();
      exit;
    }
  }
}

/**
 * Deliberately insure that this session will not be saved by sess_write(). safety
 */
function tokenauth_exit() {
  if ($_SESSION['tokenauth_auth']) {
    session_destroy();
  }
}

/**
 * Return TRUE if current page may be viewed using only a token
 */
function tokenauth_allowed_pages($path) {

  // Code from the block_list funtion in block.module.
  // If the path doesn't match any of the exeptions, return TRUE.
  $pathalias = drupal_get_path_alias($path);
  $regexp = '/^(' . preg_replace(array(
    '/(\\r\\n?|\\n)/',
    '/\\\\\\*/',
    '/(^|\\|)\\\\<front\\\\>($|\\|)/',
  ), array(
    '|',
    '.*',
    '\\1' . preg_quote(variable_get('site_frontpage', 'node'), '/') . '\\2',
  ), preg_quote(variable_get('tokenauth_pages', "rss.xml\n*/feed\n*/opml"), '/')) . ')$/';

  // Compare with the internal and path alias (if any).
  $page_match = preg_match($regexp, $pathalias);
  if ($pathalias != $path) {
    $page_match = $page_match || preg_match($regexp, $path);
  }
  if ($page_match) {
    return TRUE;
  }
  else {
    return FALSE;
  }
}

/**
 * Implementation of hook_user().
 * Boring code to change tokens. No UI yet.
 */
function tokenauth_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {
    case 'update':
      if (isset($account->tokenauth_token)) {
        $sql = "UPDATE {tokenauth_tokens} SET token = '%s' WHERE uid = %d";
        db_query($sql, $account->tokenauth_token, $account->uid);
      }
      break;
    case 'insert':
      $sql = "INSERT INTO {tokenauth_tokens} (uid, token) VALUES (%d, '%s')";
      db_query($sql, $account->uid, user_password());
      break;
    case 'delete':
      $sql = 'DELETE FROM {tokenauth_tokens} WHERE uid = %d';
      db_query($sql, $account->uid);
  }
}

Functions

Namesort descending Description
tokenauth_admin_settings Implementation of hook_settings().
tokenauth_admin_settings_validate Validate callback.
tokenauth_allowed_pages Return TRUE if current page may be viewed using only a token
tokenauth_exit Deliberately insure that this session will not be saved by sess_write(). safety
tokenauth_get_token API function for retrieving the token for a given user.
tokenauth_init Implementation of hook_init().
tokenauth_menu Implementation of hook_menu().
tokenauth_perm Implementation of hook_perm().
tokenauth_reset Reset all tokens.
tokenauth_reset_confirm Menu callback: confirm reset tokens.
tokenauth_reset_confirm_submit Handler for reset tokens confirmation
tokenauth_user Implementation of hook_user(). Boring code to change tokens. No UI yet.
tokenauth_user_profile_form Menu callback. Prints the token and instructions.
tokenauth_user_profile_form_submit
tokenauth_user_reset Reset a users token.
tokenauth_user_reset_confirm Menu callback: confirm reset users token.
tokenauth_user_reset_confirm_submit Handler for reset tokens confirmation