You are here

services_keyauth.module in Services 6.2

Same filename and directory in other branches
  1. 7 auth/services_keyauth/services_keyauth.module

Provides a key based validation system.

File

auth/services_keyauth/services_keyauth.module
View source
<?php

/**
 * @file
 *  Provides a key based validation system.
 */

/**
 * Implementation of hook_cron().
 */
function services_keyauth_cron() {

  // Clear old values from the nonce table.
  $expiry_time = time() - variable_get('services_key_expiry', 30);
  db_query("DELETE FROM {services_timestamp_nonce}\n    WHERE timestamp < '%s'", $expiry_time);
}

/**
 * Determine whether the current user has access to a keys configuration.
 */
function services_keyauth_access() {
  return user_access('administer services') && variable_get('services_use_key', TRUE);
}

/**
 * Implementation of hook_authentication_info().
 */
function services_keyauth_authentication_info() {
  return array(
    'file' => 'services_keyauth.inc',
    'title' => t('Key authentication'),
    'description' => t('The default key-based authentication'),
    'security_settings' => '_services_keyauth_security_settings',
    'security_settings_validate' => '_services_keyauth_security_settings_validate',
    'security_settings_submit' => '_services_keyauth_security_settings_submit',
    'alter_methods' => '_services_keyauth_alter_methods',
    'alter_browse_form' => '_services_keyauth_alter_browse_form',
    'alter_browse_form_submit' => '_services_keyauth_alter_browse_form_submit',
    'authenticate_call' => '_services_keyauth_authenticate_call',
  );
}

/**
 * Implementation of hook_menu().
 */
function services_keyauth_menu() {
  $items = array();
  $items['admin/build/services/keys'] = array(
    'title' => 'Keys',
    'description' => 'Manage application access to site services.',
    'page callback' => 'services_keyauth_admin_keys_list',
    'access callback' => 'services_keyauth_access',
    'type' => MENU_LOCAL_TASK,
    'file' => 'services_keyauth.admin.inc',
  );
  $items['admin/build/services/keys/%'] = array(
    'title' => 'Edit key',
    'access arguments' => array(
      'administer services',
    ),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'services_keyauth_admin_keys_form',
    ),
    'file' => 'services_keyauth.admin.inc',
    'type' => MENU_CALLBACK,
  );
  $items['admin/build/services/keys/%/delete'] = array(
    'access arguments' => array(
      'administer services',
    ),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'services_keyauth_admin_keys_delete_confirm',
      4,
    ),
    'file' => 'services_keyauth.admin.inc',
    'type' => MENU_CALLBACK,
  );
  $items['admin/build/services/keys/list'] = array(
    'title' => 'List',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'access callback' => 'services_keyauth_access',
    'weight' => -10,
  );
  $items['admin/build/services/keys/add'] = array(
    'title' => 'Create key',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'services_keyauth_admin_keys_form',
    ),
    'access callback' => 'services_keyauth_access',
    'type' => MENU_LOCAL_TASK,
    'file' => 'services_keyauth.admin.inc',
  );
  return $items;
}

/**
 * Given the necessary data, create a unique hash for key authentication.
 *
 * This hash is compared to the hash passed in by the client to verify
 * that the two match.
 *
 * @param $timestamp
 *   Current time in Unix timestamp format.
 * @param $domain
 *   A unique value to identify this request. This typically matches the
 *   client's domain, but does not have to.
 * @param $nonce
 *   A random value. 
 * @param $method
 *   The services method being called.
 * @param $args
 *   An array of argument for the method.
 *
 * @return
 *   A sha256 hash of the above data, plus the API key.
 *
 * @see _services_keyauth_authenticate_call()
 */
function services_get_hash($timestamp, $domain, $nonce, $method, $args) {
  $hash_parameters = array(
    $timestamp,
    $domain,
    $nonce,
    $method['method'],
  );
  foreach ($method['args'] as $key => $arg) {
    if (isset($arg['signed']) && $arg['signed'] == TRUE) {
      if (is_numeric($args[$key]) || !empty($args[$key])) {
        if (is_array($args[$key]) || is_object($args[$key])) {
          $hash_parameters[] = serialize($args[$key]);
        }
        else {
          $hash_parameters[] = $args[$key];
        }
      }
      else {
        $hash_parameters[] = '';
      }
    }
  }
  $api_key = db_result(db_query("SELECT kid FROM {services_keys} WHERE domain = '%s'", $domain));

  // Store Key ID so service has ability to later identify caller if this call
  // is successfully authenticated.
  _services_keyauth_set_kid($api_key);
  return hash_hmac("sha256", implode(';', $hash_parameters), $api_key);
}

/**
 * Returns Key ID of key used to authenticate call.
 *
 * @return
 *   The Key ID.
 */
function services_keyauth_get_kid() {
  return _services_keyauth_set_kid();
}

/**
 * Set or get Key ID of key used to authenticate call.
 *
 * @param
 *   A Key ID to set.
 *
 * @return
 *   The Key ID currently set.
 */
function _services_keyauth_set_kid($caller_kid = NULL) {
  static $kid;
  if (!$kid && $caller_kid) {
    $kid = $caller_kid;
  }
  return $kid;
}

/**
 * Return key information for a specified API key.
 *
 * @param $kid
 *   The Key ID for this key in the services_keys table.
 *
 * @return
 *   An object with the key's title and domain.
 */
function services_keyauth_get_key($kid) {
  $keys = services_keyauth_get_keys();
  foreach ($keys as $key) {
    if ($key->kid == $kid) {
      return $key;
    }
  }
}

/**
 * Return key information for all API keys.
 *
 * @return
 *   An associative array of objects with the key's title and domain,
 *   keyed on the Key ID.
 */
function services_keyauth_get_keys() {
  static $keys;
  if (!$keys) {
    $keys = array();
    $result = db_query("SELECT * FROM {services_keys}");
    while ($key = db_fetch_object($result)) {
      $keys[$key->kid] = $key;
    }
  }
  return $keys;
}

/**
 * Clear cache when keyauth is disabled.
 */
function services_keyauth_disable() {
  cache_clear_all('services:methods', 'cache');
}

/**
 * Clear cache when keyauth is enabled.
 */
function services_keyauth_enable() {
  cache_clear_all('services:methods', 'cache');
}

Functions

Namesort descending Description
services_get_hash Given the necessary data, create a unique hash for key authentication.
services_keyauth_access Determine whether the current user has access to a keys configuration.
services_keyauth_authentication_info Implementation of hook_authentication_info().
services_keyauth_cron Implementation of hook_cron().
services_keyauth_disable Clear cache when keyauth is disabled.
services_keyauth_enable Clear cache when keyauth is enabled.
services_keyauth_get_key Return key information for a specified API key.
services_keyauth_get_keys Return key information for all API keys.
services_keyauth_get_kid Returns Key ID of key used to authenticate call.
services_keyauth_menu Implementation of hook_menu().
_services_keyauth_set_kid Set or get Key ID of key used to authenticate call.