diff --git modules/openid/openid.api.php modules/openid/openid.api.php
index 11faa71..3fad4c7 100644
--- modules/openid/openid.api.php
+++ modules/openid/openid.api.php
@@ -52,6 +52,12 @@ function hook_openid_response($response, $account) {
  * parameter, the claimed identifier. They have to return an array of services,
  * in the same form returned by openid_discover().
  *
+ * The claimed identifier parameter should be passed by reference to the
+ * callback, because claimed id could be changed during discovery process.
+ * According to Openid specifications relying party must handle the two
+ * following HTTP redirects and the final URL must be used by the relying party
+ * as the claimed id. See http://drupal.org/node/575810 for more information.
+ *
  * The first discovery method that succeed (return at least one services) will
  * stop the discovery process.
  *
diff --git modules/openid/openid.module modules/openid/openid.module
index 7673de8..0bb3aa3 100644
--- modules/openid/openid.module
+++ modules/openid/openid.module
@@ -379,7 +379,7 @@ function openid_complete($response = array()) {
  * @return Array of services discovered (including OpenID version, endpoint
  * URI, etc).
  */
-function openid_discovery($claimed_id) {
+function openid_discovery(&$claimed_id) {
   module_load_include('inc', 'openid');
 
   $methods = module_invoke_all('openid_discovery_method_info');
@@ -418,7 +418,7 @@ function openid_openid_discovery_method_info() {
  * @see http://openid.net/specs/openid-authentication-2_0.html#discovery
  * @see hook_openid_discovery_method_info()
  */
-function _openid_xri_discovery($claimed_id) {
+function _openid_xri_discovery(&$claimed_id) {
   if (_openid_is_xri($claimed_id)) {
     // Resolve XRI using a proxy resolver (Extensible Resource Identifier (XRI)
     // Resolution Version 2.0, section 11.2 and 14.3).
@@ -444,7 +444,7 @@ function _openid_xri_discovery($claimed_id) {
  * @see http://openid.net/specs/openid-authentication-2_0.html#discovery
  * @see hook_openid_discovery_method_info()
  */
-function _openid_xrds_discovery($claimed_id) {
+function _openid_xrds_discovery(&$claimed_id) {
   $services = array();
 
   $xrds_url = $claimed_id;
@@ -452,9 +452,17 @@ function _openid_xrds_discovery($claimed_id) {
   if ($scheme == 'http' || $scheme == 'https') {
     // For regular URLs, try Yadis resolution first, then HTML-based discovery
     $headers = array('Accept' => 'application/xrds+xml');
-    $result = drupal_http_request($xrds_url, array('headers' => $headers));
+    // According to 7.2.4 There could be one or two redirects
+    $result = drupal_http_request($xrds_url, array('headers' => $headers, 'max_redirects' => 2));
 
     if (!isset($result->error)) {
+
+      // Replace user entered claimed_id if we got redirect
+      // Fixes http://drupal.org/node/575810 OpenID discovery spec violation.
+      if (!empty($result->redirect_code)) {
+        $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);
