getMessage()); drupal_add_http_header('WWW-Authenticate', sprintf('OAuth realm="%s"', url('', array('absolute' => TRUE)))); } exit; } /** * Menu callback for when something has been authorized - used in both client and provider flow * * @param $csid Should contain the id of the consumer when used in the client flow */ function oauth_common_page_authorized($csid = NULL) { // If we have an oauth_token we're acting as a consumer and just got authorized if (!empty($_GET['oauth_token'])) { //TODO: Add documentation on how to use the callback url with $consumer = $csid ? DrupalOAuthConsumer::loadById($csid, FALSE) : FALSE; if ($consumer) { $request_token = DrupalOAuthToken::loadByKey($_GET['oauth_token'], $consumer, OAUTH_COMMON_TOKEN_TYPE_REQUEST); } else { // Backwards compatibility with 6.x-3.0-beta3 $request_token = DrupalOAuthToken::load($_GET['oauth_token'], FALSE); $consumer = $request_token ? $request_token->consumer : FALSE; } if (!empty($request_token)) { $client = new DrupalOAuthClient($consumer, $request_token); $verifier = isset($_GET['oauth_verifier']) ? $_GET['oauth_verifier'] : NULL; $access_token = $client->getAccessToken(NULL, array('verifier' => $verifier)); if ($access_token) { // We recieved a new token - save it if (!$access_token->in_database) { $access_token->write(); } $request_token->delete(); module_invoke_all('oauth_common_authorized', $consumer, $access_token, $request_token); } } } return t('The application has been authorized'); } /** * Form for granting access to the consumer */ function oauth_common_form_authorize() { module_load_include('inc', 'oauth_common'); $req = DrupalOAuthRequest::from_request(); $context = oauth_common_context_from_request($req); $auth_ops = $context->authorization_options; if (!$context) { drupal_set_message(t("Can't find OAuth context, check the site's settings."), 'error'); return; } $token = $req->get_parameter('oauth_token'); $callback = $req->get_parameter('oauth_callback'); $token = DrupalOAuthToken::loadByKey($token, FALSE, OAUTH_COMMON_TOKEN_TYPE_REQUEST); // Check that we have a valid token if (!$token) { drupal_set_message(t('Please include a valid OAuth token in your request.'), 'error'); return; } $consumer = $token->consumer; // Redirect to the right form, or present an error. global $user; if ($user->uid) { // There's some strange bug in the ?destination=... handling // This is not exactly beautiful, but it gets the work done // TODO: Find out why! if (drupal_substr($_SERVER['REQUEST_URI'], 0, 2) == '//') { header('Location: ' . drupal_substr($_SERVER['REQUEST_URI'], 1), TRUE, 302); } if (!(user_access('oauth authorize any consumers') || user_access('oauth authorize consumers in ' . $consumer->context))) { drupal_set_message(t('You are not authorized to allow external services access to this system.'), 'error'); return drupal_access_denied(); } if (!empty($auth_ops['automatic_authorization']) && $auth_ops['automatic_authorization'] && !empty($consumer->callback_url)) { // Authorize the request token $token->uid = $user->uid; $token->authorized = 1; $token->services = $context->authorization_options['default_authorization_levels']; $token->write(TRUE); // Pick the callback url apart and add the token parameter $callback = parse_url($consumer->callback_url); $query = array(); parse_str($callback['query'], $query); $query['oauth_token'] = $token->key; $callback['query'] = http_build_query($query, 'idx_', '&'); // Return to the consumer site header('Location: ' . _oauth_common_glue_url($callback), TRUE, 302); exit; } $tvars = array( '@user' => $user->name, '@appname' => $consumer->name, '@sitename' => variable_get('site_name', ''), ); $title = !empty($context->title) ? $context->title : 'Authorize @appname'; drupal_set_title(t($title, $tvars), PASS_THROUGH); $form = array(); $form['token'] = array( '#type' => 'value', '#value' => $token, ); $message = !empty($auth_ops['message']) ? $auth_ops['message'] : 'The application @appname wants to access @sitename on your behalf, check the permissions that you would like the application to have.'; $form['message'] = array( '#type' => 'item', '#markup' => t($message, $tvars), ); $message = !empty($auth_ops['warning']) ? $auth_ops['warning'] : 'If you don\'t know what @appname is, or don\'t want to give it access to your content, just click here and we\'ll take you away from this page without granting @appname any access to @sitename.'; $form['warning'] = array( '#type' => 'item', '#markup' => l(t($message, $tvars), 'oauth/authorization/deny/' . $token->key), '#attributes' => array( 'class' => array('abort-authorization'), ), ); $disable_selection = !empty($auth_ops['disable_auth_level_selection']) && !empty($auth_ops['default_authorization_levels']) && $auth_ops['disable_auth_level_selection']; if (!$disable_selection) { $authorization_title = !empty($auth_ops['authorization_title']) ? $auth_ops['authorization_title'] : 'Permissions'; $form['authorization'] = array( '#type' => 'fieldset', '#title' => t($authorization_title, $tvars), ); $form['authorization']['levels'] = array( '#tree' => TRUE, ); foreach ($context->authorization_levels as $name => $level) { $auth_level_opt = array( '#type' => 'checkbox', '#title' => t($level['title'], $tvars), '#description' => t($level['description'], $tvars), '#value' => $level['default'], ); $form['authorization']['levels'][$name] = $auth_level_opt; } } else { $form['authorization']['levels'] = array( '#tree' => TRUE, ); foreach ($auth_ops['default_authorization_levels'] as $level) { $form['authorization']['levels'][$level] = array( '#type' => 'value', '#value' => $level, ); } } $deny_title = !empty($auth_ops['deny_access_title']) ? $auth_ops['deny_access_title'] : 'Deny access'; $form['deny'] = array( '#type' => 'item', '#markup' => l(t($deny_title), 'oauth/authorization/deny/' . $token->key), '#attributes' => array( 'class' => array('deny-access'), ), ); $grant_title = !empty($auth_ops['grant_access_title']) ? $auth_ops['grant_access_title'] : 'Grant access'; $form['actions'] = array('#type' => 'actions'); $form['actions']['confirm'] = array( '#type' => 'submit', '#value' => t($grant_title), ); return $form; } else { $query = $_GET; unset($query['q']); // why are there so few q's? drupal_goto('user/login', array('query' => array( 'destination' => url('oauth/authorize', array( 'query' => $query, )), ))); } } /** * Validation of the form for granting access to the consumer */ function oauth_common_form_authorize_validate($form, &$form_state) { $values = $form_state['values']; $got_permission = FALSE; $consumer = $values['token']->consumer; $context = oauth_common_context_load($consumer->context); if (!$context) { form_set_error('confirm', t("Can't find OAuth context.")); return; } if (!$context->authorization_options['disable_auth_level_selection']) { foreach ($context->authorization_levels as $name => $level) { if ($values['levels'][$name]) { $got_permission = TRUE; break; } } if (!$got_permission) { form_set_error('confirm', t("You haven't given the application access to anything. Click on 'Deny access' or just close this window if you don't want to authorize it.")); } } } /** * Form submit handler that grants access to the consumer */ function oauth_common_form_authorize_submit(&$form, &$form_state) { global $user; $values = $form_state['values']; // Save the list of all services that the user allowed the // consumer to do $token = $values['token']; $token->uid = $user->uid; $token->authorized = 1; $consumer = $token->consumer; $context = oauth_common_context_load($consumer->context); if (!$context) { drupal_set_message(t("Can't find OAuth context, check the site's settings."), 'error'); return; } // Add services if (!empty($values['full_access'])) { // TODO: Full access should be a configurable auth level $token->services = array('*'); } elseif (!empty($values['levels'])) { $token->services = array_keys(array_filter($values['levels'])); } else { $token->services = array(); } $token->write(TRUE); if (!empty($consumer->callback_url) && $consumer->callback_url !== 'oob') { // Pick the callback url apart and add the token parameter $callback = parse_url($consumer->callback_url); $query = array(); if (!empty($callback['query'])) { parse_str($callback['query'], $query); } $query['oauth_token'] = $token->key; $callback['query'] = http_build_query($query, 'idx_', '&'); // Return to the consumer site header('Location: ' . _oauth_common_glue_url($callback), TRUE, 302); exit; } else { drupal_goto('oauth/authorized'); } } /** * Constructs the url to which to return someone who has asked for access to a consumer */ function _oauth_common_glue_url($parsed) { $uri = isset($parsed['scheme']) ? $parsed['scheme'] . '://' : ''; $uri .= isset($parsed['user']) ? $parsed['user'] . (isset($parsed['pass']) ? ':' . $parsed['pass'] : '') . '@' : ''; $uri .= isset($parsed['host']) ? $parsed['host'] : ''; $uri .= isset($parsed['port']) ? ':' . $parsed['port'] : ''; if (isset($parsed['path'])) { $uri .= (substr($parsed['path'], 0, 1) == '/') ? $parsed['path'] : ((!empty($uri) ? '/' : '' ) . $parsed['path']); } $uri .= isset($parsed['query']) ? '?' . $parsed['query'] : ''; return $uri; } /** * Generate a request token from the request. */ function oauth_common_callback_request_token() { try { $req = DrupalOAuthRequest::from_request(); $context = oauth_common_context_from_request($req); if (!$context) { throw new OAuthException('No OAuth context found'); } $server = new DrupalOAuthServer($context); print $server->fetch_request_token($req); } catch (OAuthException $e) { drupal_add_http_header('Status', '401 Unauthorized: ' . $e->getMessage()); drupal_add_http_header('WWW-Authenticate', sprintf('OAuth realm="%s"', url('', array('absolute' => TRUE)))); } } /** * Get a access token for the request */ function oauth_common_callback_access_token() { try { $req = DrupalOAuthRequest::from_request(); $context = oauth_common_context_from_request($req); if (!$context) { throw new OAuthException('No OAuth context found'); } $server = new DrupalOAuthServer($context); $access_token = $server->fetch_access_token($req); // Set the expiry time based on context settings or get parameter $expires = !empty($context->authorization_options['access_token_lifetime']) ? REQUEST_TIME + $context->authorization_options['access_token_lifetime'] : 0; if ($_GET['expires'] && intval($_GET['expires'])) { $hint = intval($_GET['expires']); // Only accept more restrictive expiry times if ($expires == 0 || $hint < $expires) { $expires = $hint; } } // Store the expiry time if the access token should expire if ($expires) { $access_token->expires = $expires; $access_token->write(TRUE); } print $access_token; } catch (OAuthException $e) { drupal_add_http_header('Status', '401 Unauthorized: ' . $e->getMessage()); drupal_add_http_header('WWW-Authenticate', sprintf('OAuth realm="%s"', url('', array('absolute' => TRUE)))); } }