services_api_key_auth.module in Services API Key Authentication 7
Same filename and directory in other branches
Extend services to allow API key authentication on endpoints.
File
services_api_key_auth.moduleView source
<?php
/**
* @file
* Extend services to allow API key authentication on endpoints.
*/
/**
* Implements hook_services_authentication_info().
*/
function services_api_key_auth_services_authentication_info() {
return array(
'title' => t('API key authentication'),
'description' => t('Enable API Key authentication for an endpoint.'),
'authenticate_call' => 'services_api_key_auth_services_authenticate',
'security_settings' => 'services_api_key_auth_services_settings_form',
);
}
/**
* Apply authentication rules.
*/
function services_api_key_auth_services_authenticate() {
// Get function arguments.
$args = func_get_args();
// Get the key from the request.
$api_key = '';
switch ($args[0]['api_key_source']) {
case 'request':
$api_key = empty($_REQUEST['api-key']) ? '' : $_REQUEST['api-key'];
break;
case 'header':
$api_key = empty($_SERVER['HTTP_API_KEY']) ? '' : $_SERVER['HTTP_API_KEY'];
break;
}
// Validate request.
$valid = (bool) services_api_key_auth_compare_key($api_key, $args[0]['api_key']);
// Allow other modules to have their say.
drupal_alter('services_api_key_valid', $valid, $args);
if ($valid) {
// If a valid request, switch to user to perform drupal response.
if (!empty($args[0]['user'])) {
global $user;
$current_user = user_load_by_name($args[0]['user']);
if (!empty($current_user)) {
$user = $current_user;
drupal_session_regenerate();
drupal_add_http_header('Cache-Control', 'no-cache, must-revalidate, post-check=0, pre-check=0');
}
}
return FALSE;
}
return services_error('Unauthorised access.', 403);
}
/**
* Build form for authentication settings.
*
* @param $settings
* The settings as they exist currently.
* @return
* The form definition.
*/
function services_api_key_auth_services_settings_form($settings) {
$form = array();
// Generate an API key for the user.
$key = drupal_random_key(16);
// Text field for api key.
$form['api_key'] = array(
'#type' => 'textfield',
'#title' => t('API Key'),
'#description' => t('Enter an API key to allow access to this endpoint. You can use a secure pseudo-random key generated on your behalf, "!key", entered automatically if the field was empty.', array(
'!key' => $key,
)),
'#default_value' => !empty($settings['api_key']) ? $settings['api_key'] : $key,
);
// Define where we should look up of the API key value.
$form['api_key_source'] = array(
'#type' => 'select',
'#title' => t('API Key source'),
'#description' => t('Where the API key can be found, either in the request parameters or in the HTTP header. Note that the <a href="@href_php_net" target="_blank">@var_request</a> variable contains the contents of @var_get, @var_post and @var_cookie, and that for the header option, <em>api-key</em> should still be the parameter passed in the request. The Web server will convert this to <em>HTTP_API_KEY</em> on receipt.', array(
'@href_php_net' => 'http://php.net/manual/en/reserved.variables.request.php',
'@var_request' => '$_REQUEST',
'@var_cookie' => '$_COOKIE',
'@var_post' => '$_POST',
'@var_get' => '$_GET',
)),
'#options' => array(
'request' => t("Request (\$_REQUEST['api-key'])"),
'header' => t("Header (\$_SERVER['HTTP_API_KEY'])"),
),
'#default_value' => empty($settings['api_key_source']) ? 'request' : $settings['api_key_source'],
);
// Get list of users with given role.
$role = user_role_load_by_name(variable_get('service_api_key_role', 'administrator'));
$query = 'SELECT DISTINCT(ur.uid) FROM {users_roles} AS ur WHERE ur.rid = :rids';
$result = db_query($query, array(
':rids' => $role->rid,
));
$options = array(
'' => 'Select user',
);
while ($uid = $result
->fetchColumn()) {
$user = user_load($uid);
$options[$user->name] = $user->name;
unset($user);
}
// Build select field.
$form['user'] = array(
'#type' => 'select',
'#title' => t('User'),
'#description' => t('Select the user to run request through this endpoint as.'),
'#options' => $options,
'#default_value' => !empty($settings['user']) ? $settings['user'] : '',
);
return $form;
}
/**
* Compare api key.
*
* @param $a string
* Token string.
* @param $b string
* Token string.
*
* @return boolean
*/
function services_api_key_auth_compare_key($a, $b) {
if (strlen($a) !== strlen($b)) {
return FALSE;
}
$result = 0;
for ($i = 0; $i < strlen($a); $i++) {
$result |= ord($a[$i]) ^ ord($b[$i]);
}
return $result == 0;
}
/**
* Implements hook_menu().
*/
function services_api_key_auth_menu() {
return array(
'admin/structure/services/api_key_settings' => array(
'title' => 'API Key settings',
'description' => 'Set user role for user list in API Key authentication settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'services_api_key_auth_admin_settings',
),
'access arguments' => array(
'administer services',
),
'type' => MENU_LOCAL_TASK,
),
);
}
/**
* Define form for admin screen.
*
* @see services_api_key_auth_admin_settings_submit()
*/
function services_api_key_auth_admin_settings() {
// Get available roles.
$roles = user_roles();
// Build field options.
$options = array();
foreach ($roles as $role) {
$options[$role] = $role;
}
// Build form.
$form = array();
$form['fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('User settings'),
'#description' => t('Set the user role to be used when loading the list of users to pick from when configuring the API Key Authentication settings on an endpoint.'),
);
$form['fieldset']['role'] = array(
'#type' => 'select',
'#title' => t('User role'),
'#options' => $options,
'#default_value' => variable_get('service_api_key_role', 'administrator'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save settings'),
);
return $form;
}
/**
* Process admin form submission.
*
* @see services_api_key_auth_admin_settings()
*/
function services_api_key_auth_admin_settings_submit($form, &$state) {
variable_set('service_api_key_role', $state['values']['role']);
drupal_set_message('Settings saved.');
}
Functions
Name | Description |
---|---|
services_api_key_auth_admin_settings | Define form for admin screen. |
services_api_key_auth_admin_settings_submit | Process admin form submission. |
services_api_key_auth_compare_key | Compare api key. |
services_api_key_auth_menu | Implements hook_menu(). |
services_api_key_auth_services_authenticate | Apply authentication rules. |
services_api_key_auth_services_authentication_info | Implements hook_services_authentication_info(). |
services_api_key_auth_services_settings_form | Build form for authentication settings. |