123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- <?php
- define('OAUTH_COMMON_CODE_BRANCH', '6.x-3.x');
- define('OAUTH_COMMON_TOKEN_TYPE_REQUEST', 0);
- define('OAUTH_COMMON_TOKEN_TYPE_ACCESS', 1);
- define('OAUTH_COMMON_VERSION_1', 1); // The original 1.0 spec
- define('OAUTH_COMMON_VERSION_1_RFC', 2); // The RFC 5849 1.0 spec
- //TODO: Don't act as a provider by default.
- //TODO: Check for other functions with breaking changes
- //TODO: Move admin pages to more regular places
- //TODO: Add watchdog messages about deprecated methods?
- //TODO: Move provider ui related pages to provider ui
- /**
- * Implements hook_permission().
- */
- function oauth_common_permission() {
- $permissions = array(
- 'oauth authorize any consumers' => array(
- 'title' => t('Authorize any OAuth consumers'),
- 'restrict access' => TRUE,
- ),
- 'oauth register any consumers' => array(
- 'title' => t('Register any OAuth consumers'),
- 'restrict access' => TRUE,
- ),
- 'administer oauth' => array(
- 'title' => t('Administer OAuth'),
- 'restrict access' => TRUE,
- ),
- 'administer consumers' => array(
- 'title' => t('Administer OAuth consumers'),
- 'restrict access' => TRUE,
- ),
- );
- // Add seperate permissions for creating and
- // authorizing consumers in each context.
- foreach (oauth_common_context_list() as $name => $title) {
- $permissions[sprintf('oauth register consumers in %s', $name)] = array(
- 'title' => t('Register OAuth consumers in %context', array('%context' => $title)),
- );
- $permissions[sprintf('oauth authorize consumers in %s', $name)] = array(
- 'title' => t('Authorize OAuth consumers in %context', array('%context' => $title)),
- );
- }
- return $permissions;
- }
- /**
- * Implements hook_menu().
- */
- function oauth_common_menu() {
- $menu = array();
- $admin_base = array(
- 'access arguments' => array('administer oauth'),
- 'file' => 'oauth_common.admin.inc',
- );
- $menu['admin/config/services/oauth'] = array(
- 'title' => 'OAuth',
- 'description' => 'Settings for OAuth',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('_oauth_common_admin'),
- 'type' => MENU_NORMAL_ITEM,
- ) + $admin_base;
- $menu['admin/config/services/oauth/settings'] = array(
- 'title' => 'Settings',
- 'description' => 'Settings for OAuth',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('_oauth_common_admin'),
- 'type' => MENU_DEFAULT_LOCAL_TASK,
- 'weight' => 0,
- ) + $admin_base;
- // OAuth doesn't need different endpoints for the different context as all
- // actions are done with a specific consumer, which in itself is associated
- // with a context.
- $provider_base = array(
- 'access callback' => 'oauth_commmon_is_provider',
- 'file' => 'oauth_common.pages.inc',
- 'type' => MENU_CALLBACK,
- );
- // The endpoint that consumers use to get a request token.
- $menu['oauth/request_token'] = array(
- 'page callback' => 'oauth_common_callback_request_token',
- ) + $provider_base;
- // The page a user gets sent to to authorize a request token.
- $menu['oauth/authorize'] = array(
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('oauth_common_form_authorize'),
- ) + $provider_base;
- // The endpoint that consumers use to get a access token.
- $menu['oauth/access_token'] = array(
- 'page callback' => 'oauth_common_callback_access_token',
- ) + $provider_base;
- // This page is used both in consumer and provider mode. For consumers it is
- // the callback url and triggers hook_oauth_common_authorized(). For
- // providers it is the page where users end up if no callback url exists.
- $menu['oauth/authorized'] = array(
- 'title' => 'Authorization finished',
- 'page callback' => 'oauth_common_page_authorized',
- 'access arguments' => array('access content'),
- 'file' => 'oauth_common.pages.inc',
- 'type' => MENU_CALLBACK,
- );
- // TODO: Different structures makes sense depending on whether oauth_common is
- // acting as a provider or as a consumer.
- $menu['oauth/test/valid-consumer'] = array(
- 'file' => 'oauth_common.pages.inc',
- 'page callback' => '_oauth_common_validate_request_callback',
- 'page arguments' => array('consumer'),
- 'access callback' => 'oauth_commmon_is_provider',
- 'type' => MENU_CALLBACK,
- );
- $menu['oauth/test/valid-access-token'] = array(
- 'file' => 'oauth_common.pages.inc',
- 'page callback' => '_oauth_common_validate_request_callback',
- 'page arguments' => array('access token'),
- 'access callback' => 'oauth_commmon_is_provider',
- 'type' => MENU_CALLBACK,
- );
- return $menu;
- }
- /**
- * Menu system wildcard loader for provider consumers.
- *
- * @param string $key
- */
- function oauth_common_consumer_load($csid) {
- $consumer = DrupalOAuthConsumer::loadById($csid, TRUE);
- if (!$consumer) {
- $consumer = FALSE;
- }
- return $consumer;
- }
- /**
- * Menu system wildcard loader for provider tokens.
- *
- * @param string $key
- */
- function oauth_common_provider_token_load($tid) {
- $token = DrupalOAuthToken::loadByID($tid);
- if (!$token) {
- $token = FALSE;
- }
- return $token;
- }
- /**
- * Implements hook_cron().
- */
- function oauth_common_cron() {
- $token_condition = db_and()->condition('expires', 0, '<>')->condition('expires', REQUEST_TIME, '<=');
- db_delete('oauth_common_provider_token')
- ->condition('tid', db_select('oauth_common_token', 't')->condition($token_condition)->fields('t', array('tid')), 'IN')
- ->execute();
- db_delete('oauth_common_token')
- ->condition($token_condition)
- ->execute();
- // Should 300 be overriden in DrupalOAuthServer and made configurable?
- db_delete('oauth_common_nonce')
- ->condition('timestamp', REQUEST_TIME - 300, '<')
- ->execute();
- }
- /**
- * Implements hook_oauth_default_contexts().
- */
- function oauth_common_default_oauth_common_context() {
- $contexts = array();
- $context = new stdClass;
- $context->disabled = FALSE; /* Edit this to true to make a default context disabled initially */
- $context->name = 'default';
- $context->title = 'Default context';
- $context->authorization_options = array();
- $context->authorization_levels = array(
- '*' => array(
- 'title' => 'Full access',
- 'description' => 'This will give @appname the same permissions that you normally have and will allow it to access the full range of services that @sitename provides.',
- ),
- 'read' => array(
- 'title' => 'Read access',
- 'description' => 'This will allow @appname to fetch content that you have access to on @sitename.',
- ),
- 'update' => array(
- 'title' => 'Update access',
- 'description' => 'This will allow @appname to update content that you have permissions to edit.',
- ),
- 'create' => array(
- 'title' => 'Create access',
- 'description' => 'This will allow @appname to create new content on @sitename.',
- ),
- 'delete' => array(
- 'title' => 'Delete access',
- 'description' => 'This will allow @appname to delete content from @sitename.',
- ),
- );
- $contexts[$context->name] = $context;
- return $contexts;
- }
- /**
- * Implements hook_user_delete().
- */
- function oauth_common_user_delete($account) {
- // Delete all tokens and consumers related to a user
- module_load_include('inc', 'oauth_common');
- $consumer_condition = db_select('oauth_common_provider_consumer', 'c')->condition('uid', $account->uid)->fields('c', array('csid'));
- $token_condition = db_or()->condition('uid', $account->uid)->condition('csid', $consumer_condition, 'IN');
- db_delete('oauth_common_provider_token')
- ->condition('tid', db_select('oauth_common_token', 't')->condition($token_condition)->fields('t', array('tid')), 'IN')
- ->execute();
- db_delete('oauth_common_token')
- ->condition($token_condition)
- ->execute();
- db_delete('oauth_common_consumer')
- ->condition('csid', $consumer_condition, 'IN')
- ->execute();
- db_delete('oauth_common_provider_consumer')
- ->condition('uid', $account->uid)
- ->execute();
- }
- /**
- * Implements hook_xrds().
- */
- function services_oauth_xrds() {
- $xrds = array();
- $xrds['oauth'] = array(
- 'services' => array(
- array(
- 'data' => array(
- 'Type' => array('http://oauth.net/discovery/1.0'),
- 'URI' => array('#main'),
- ),
- ),
- array(
- 'data' => array(
- 'Type' => array(
- 'http://oauth.net/core/1.0/endpoint/request',
- 'http://oauth.net/core/1.0/parameters/auth-header',
- 'http://oauth.net/core/1.0/parameters/uri-query',
- 'http://oauth.net/core/1.0/signature/HMAC-SHA1',
- ),
- 'URI' => array(url('oauth/request_token', array('absolute' => TRUE))),
- ),
- ),
- array(
- 'data' => array(
- 'Type' => array(
- 'http://oauth.net/core/1.0/endpoint/authorize',
- 'http://oauth.net/core/1.0/parameters/uri-query',
- ),
- 'URI' => array(url('oauth/authorize', array('absolute' => TRUE))),
- ),
- ),
- array(
- 'data' => array(
- 'Type' => array(
- 'http://oauth.net/core/1.0/endpoint/access',
- 'http://oauth.net/core/1.0/parameters/auth-header',
- 'http://oauth.net/core/1.0/parameters/uri-query',
- 'http://oauth.net/core/1.0/signature/HMAC-SHA1',
- ),
- 'URI' => array(url('oauth/access_token', array('absolute' => TRUE))),
- ),
- ),
- ),
- );
- return $xrds;
- }
- /**
- * Access callback function used by several menu items.
- *
- * @param stdClass $user
- * A user object.
- * @param string $permission
- * The permission that is needed in addition to edit access on the $user.
- */
- function _oauth_common_user_access($user, $permission = NULL) {
- return user_edit_access($user) && (empty($permission) || user_access($permission));
- }
- /**
- * Checks if the user has permission to edit the consumer. Edit access is
- * granted if the user has the 'administer consumers' permission or may
- * edit the account connected to the consumer.
- *
- * @param DrupalOAuthConsumer $consumer
- * @return bool
- */
- function oauth_common_can_edit_consumer($consumer) {
- $may_edit = user_access('administer consumers');
- // If the user doesn't have consumer admin privileges, check for account
- // edit access.
- if (!$may_edit && $consumer->uid) {
- $user = user_load($consumer->uid);
- $may_edit = user_edit_access($user);
- }
- return $may_edit;
- }
- /**
- * Deterines if a user has the necessary permissions to create consumers.
- *
- * @param object $account
- * The user account to check permissions for. Defaults to the currently
- * logged in user.
- * @return bool
- */
- function oauth_common_can_create_consumers($account = NULL) {
- global $user;
- if (!$account) {
- $account = $user;
- }
- $can_register_consumers = user_access('oauth register any consumers', $account);
- if (!$can_register_consumers) {
- foreach (oauth_common_context_list() as $context => $title) {
- $can_register_consumers = $can_register_consumers || user_access(sprintf('oauth register consumers in %s', $context), $account);
- }
- }
- return $can_register_consumers;
- }
- /**
- * This function is used as a access callback
- * when the authentication of the request shouldn't be
- * done by the menu system.
- *
- * @return bool
- * Always returns TRUE
- */
- function _oauth_common_always_true() {
- return TRUE;
- }
- /**
- * Access callback that checks if a user may create authorizations in the
- * consumers context.
- *
- * @param DrupalOAuthConsumer $consumer
- * @return bool
- */
- function oauth_common_can_authorize_consumer($consumer) {
- return user_access(sprintf('oauth authorize consumers in %s', $consumer->context));
- }
- /**
- * Check if oauth_common is acting as a provider.
- */
- function oauth_commmon_is_provider() {
- return variable_get('oauth_common_enable_provider', TRUE);
- }
- /**
- * Gets a request token from a oauth provider and returns the authorization
- * url. The request token is saved in the database.
- *
- * @param OAuthToken $consumer_token
- * The consumer token to use
- * @param string $request_endpoint
- * Optional. Pass a custom endpoint if needed. Defaults to '/oauth/request_token'.
- * @param string $authorize_endpoint
- * Optional. Pass a custom endpoint if needed. Defaults to '/oauth/authorize'.
- * @return string
- * The url that the client should be redirected to to authorize
- * the request token.
- */
- function oauth_common_get_request_token($consumer_token, $request_endpoint = '/oauth/request_token', $authorize_endpoint = '/oauth/authorize') {
- $client = new DrupalOAuthClient($consumer_token);
- $request_token = $client->getRequestToken($request_endpoint);
- $request_token->write();
- return $client->getAuthorizationUrl($authorize_endpoint);
- }
- /**
- * Gets the tokens for a user.
- *
- * @param string $uid
- * @param string $type
- * @return array
- */
- function oauth_common_get_user_provider_tokens($uid) {
- $res = db_query("SELECT t.*, pt.created, pt.changed, pt.services, pt.authorized FROM {oauth_common_token} t
- INNER JOIN {oauth_common_provider_token} pt WHERE t.uid = :uid AND t.type = :type", array(
- ':uid' => $uid,
- ':type' => OAUTH_COMMON_TOKEN_TYPE_ACCESS,
- ));
- $tokens = array();
- while ($token = DrupalOAuthToken::fromResult($res)) {
- $tokens[] = $token;
- }
- return $tokens;
- }
- /**
- * Create a new context with defaults appropriately set from schema.
- *
- * @return stdClass
- * An context initialized with the default values.
- */
- function oauth_common_context_new() {
- if (!module_exists('ctools')) {
- return FALSE;
- }
- ctools_include('export');
- return ctools_export_new_object('oauth_common_context');
- }
- /**
- * Load a single context.
- *
- * @param string $name
- * The name of the context.
- * @return stdClass
- * The context configuration.
- */
- function oauth_common_context_load($name) {
- if (!module_exists('ctools')) {
- return FALSE;
- }
- ctools_include('export');
- $result = ctools_export_load_object('oauth_common_context', 'names', array($name));
- if (isset($result[$name])) {
- return $result[$name];
- }
- else {
- return FALSE;
- }
- }
- /**
- * Loads the context for a request.
- *
- * @param OAuthRequest $request
- * @return object
- * The context configuration.
- */
- function oauth_common_context_from_request($request) {
- $context = NULL;
- $consumer_key = $request->get_parameter('oauth_consumer_key');
- $token_key = $request->get_parameter('oauth_token');
- if (empty($consumer_key) && !empty($token_key)) {
- $token = DrupalOAuthToken::loadByKey($token_key, FALSE, OAUTH_COMMON_TOKEN_TYPE_REQUEST);
- if ($token) {
- $consumer = $token->consumer;
- }
- }
- if (!empty($consumer_key)) {
- $consumer = DrupalOAuthConsumer::loadProviderByKey($consumer_key);
- }
- if (!empty($consumer)) {
- $context = oauth_common_context_load($consumer->context);
- }
- return $context;
- }
- /**
- * Load all contexts.
- *
- * @return array
- * Array of context objects keyed by context names.
- */
- function oauth_common_context_load_all() {
- if (!module_exists('ctools')) {
- return FALSE;
- }
- ctools_include('export');
- return ctools_export_load_object('oauth_common_context');
- }
- /**
- * Saves an context in the database.
- *
- * @return void
- */
- function oauth_common_context_save($context) {
- $update = (isset($context->cid)) ? array('cid') : array();
- drupal_write_record('oauth_common_context', $context, $update);
- }
- /**
- * Remove an context.
- *
- * @return void
- */
- function oauth_common_context_delete($context) {
- db_delete('oauth_common_context')
- ->condition('name', $context->name)
- ->condition('cid', $context->cid)
- ->execute();
- }
- /**
- * Export an context.
- *
- * @return string
- */
- function oauth_common_context_export($context, $indent = '') {
- if (!module_exists('ctools')) {
- return FALSE;
- }
- ctools_include('export');
- $output = ctools_export_object('oauth_common_context', $context, $indent);
- return $output;
- }
- /**
- * Lists all available contexts.
- *
- * @return array
- */
- function oauth_common_context_list() {
- $return = array();
- $contexts = oauth_common_context_load_all();
- if ($contexts) {
- foreach ($contexts as $context) {
- $return[$context->name] = $context->title;
- }
- }
- return $return;
- }
- /**
- * Finds the current version of the OAuth module, used in eg. user agents
- *
- * @return string
- */
- function _oauth_common_version() {
- static $version;
- if (!isset($version)) {
- $info = db_query("SELECT info FROM {system} WHERE name = 'oauth_common'")->fetchField();
- $info = $info ? unserialize($info) : FALSE;
- if (!$info || empty($info['version'])) {
- $version = OAUTH_COMMON_CODE_BRANCH;
- }
- else {
- $version = $info['version'];
- }
- }
- return $version;
- }
|