diff --git a/modules/openid/openid.api.php b/modules/openid/openid.api.php index 11faa71..b94fa86 100644 --- a/modules/openid/openid.api.php +++ b/modules/openid/openid.api.php @@ -49,8 +49,9 @@ function hook_openid_response($response, $account) { * Allow modules to declare OpenID discovery methods. * * The discovery function callbacks will be called in turn with an unique - * parameter, the claimed identifier. They have to return an array of services, - * in the same form returned by openid_discover(). + * parameter, the claimed identifier. They have to return a structured array + * with arrays of services and claimed id in the same form returned by + * openid_discover(). * * The first discovery method that succeed (return at least one services) will * stop the discovery process. diff --git a/modules/openid/openid.module b/modules/openid/openid.module index 7673de8..112bbbc 100644 --- a/modules/openid/openid.module +++ b/modules/openid/openid.module @@ -256,22 +256,30 @@ function openid_login_validate($form, &$form_state) { function openid_begin($claimed_id, $return_to = '', $form_values = array()) { module_load_include('inc', 'openid'); + $service = NULL; $claimed_id = openid_normalize($claimed_id); - $services = openid_discovery($claimed_id); - $service = _openid_select_service($services); + $discovery = openid_discovery($claimed_id); + if (!empty($discovery['services'])) { + $service = _openid_select_service($discovery['services']); + } if (!$service) { form_set_error('openid_identifier', t('Sorry, that is not a valid OpenID. Ensure you have spelled your ID correctly.')); return; } + // Set claimed id from discovery. + if (!empty($service['claimed_id'])) { + $claimed_id = $discovery['claimed_id']; + } + // Store discovered information in the users' session so we don't have to rediscover. $_SESSION['openid']['service'] = $service; // Store the claimed id $_SESSION['openid']['claimed_id'] = $claimed_id; // Store the login form values so we can pass them to - // user_exteral_login later. + // user_external_login later. $_SESSION['openid']['user_login_values'] = $form_values; // If a supported math library is present, then create an association. @@ -348,9 +356,9 @@ function openid_complete($response = array()) { // identififer to make sure that the provider is authorized to // respond on behalf of this. if ($response['openid.claimed_id'] != $claimed_id) { - $services = openid_discovery($response['openid.claimed_id']); + $discovery = openid_discovery($response['openid.claimed_id']); $uris = array(); - foreach ($services as $discovered_service) { + foreach ($discovery['services'] as $discovered_service) { if (in_array('http://specs.openid.net/auth/2.0/server', $discovered_service['types']) || in_array('http://specs.openid.net/auth/2.0/signon', $discovered_service['types'])) { $uris[] = $discovered_service['uri']; } @@ -376,8 +384,8 @@ function openid_complete($response = array()) { * * @param $claimed_id The OpenID URL to perform discovery on. * - * @return Array of services discovered (including OpenID version, endpoint - * URI, etc). + * @return Structured array of discovered claimed_id and array of services + * (including OpenID version, endpoint URI, etc). */ function openid_discovery($claimed_id) { module_load_include('inc', 'openid'); @@ -385,11 +393,11 @@ function openid_discovery($claimed_id) { $methods = module_invoke_all('openid_discovery_method_info'); drupal_alter('openid_discovery_method_info', $methods); - // Execute each method in turn. + // Execute each method in turn and return first successful discovery. foreach ($methods as $method) { - $discovered_services = $method($claimed_id); - if (!empty($discovered_services)) { - return $discovered_services; + $discovery = $method($claimed_id); + if (!empty($discovery)) { + return $discovery; } } @@ -423,18 +431,22 @@ function _openid_xri_discovery($claimed_id) { // Resolve XRI using a proxy resolver (Extensible Resource Identifier (XRI) // Resolution Version 2.0, section 11.2 and 14.3). $xrds_url = variable_get('xri_proxy_resolver', 'http://xri.net/') . rawurlencode($claimed_id) . '?_xrd_r=application/xrds+xml'; - $services = _openid_xrds_discovery($xrds_url); - foreach ($services as $i => &$service) { - $status = $service['xrd']->children(OPENID_NS_XRD)->Status; - if ($status && $status->attributes()->cid == 'verified') { - $service['claimed_id'] = openid_normalize((string)$service['xrd']->children(OPENID_NS_XRD)->CanonicalID); + $discovery = _openid_xrds_discovery($xrds_url); + if (!empty($discovery['services']) && is_array($discovery['services'])) { + foreach ($discovery['services'] as $i => &$service) { + $status = $service['xrd']->children(OPENID_NS_XRD)->Status; + if ($status && $status->attributes()->cid == 'verified') { + $service['claimed_id'] = openid_normalize((string)$service['xrd']->children(OPENID_NS_XRD)->CanonicalID); + } + else { + // Ignore service if Canonical ID could not be verified. + unset($discovery['services'][$i]); + } } - else { - // Ignore service if CanonicalID could not be verified. - unset($services[$i]); + if (!empty($discovery['services'])) { + return $discovery; } } - return $services; } } @@ -454,7 +466,18 @@ function _openid_xrds_discovery($claimed_id) { $headers = array('Accept' => 'application/xrds+xml'); $result = drupal_http_request($xrds_url, array('headers' => $headers)); - if (!isset($result->error)) { + // Check for HTTP error and make sure, that we reach the target. If maximum + // allowed redirects are exhausted, final destination URL isn't reached, but + // drupal_http_request will not return error. + // @todo Remove the check for 200 HTTP result code after the following issue + // will be fixed: http://drupal.org/node/1096890. + if (!isset($result->error) && $result->code == 200) { + + // Replace user entered claimed_id if we got redirect + if (!empty($result->redirect_url)) { + $claimed_id = openid_normalize($result->redirect_url); + } + if (isset($result->headers['content-type']) && preg_match("/application\/xrds\+xml/", $result->headers['content-type'])) { // Parse XML document to find URL $services = _openid_xrds_parse($result->data); @@ -500,7 +523,13 @@ function _openid_xrds_discovery($claimed_id) { } } } - return $services; + + if (!empty($services)) { + return array( + 'services' => $services, + 'claimed_id' => $claimed_id, + ); + } } /**