diff --git a/modules/openid/openid.api.php b/modules/openid/openid.api.php
index 11faa71..d1955ae 100644
--- a/modules/openid/openid.api.php
+++ b/modules/openid/openid.api.php
@@ -52,6 +52,13 @@ 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 all following
+ * HTTP redirects and apply rules in Section 6 of [RFC3986] to the final
+ * destination URL. 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 a/modules/openid/openid.module b/modules/openid/openid.module
index 7673de8..45ec293 100644
--- a/modules/openid/openid.module
+++ b/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;
@@ -454,7 +454,19 @@ 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 or for redirect code. Redirect code means that
+    // maximum number of allowed redirects was spent but the final target wasn't
+    // reached.
+    // TODO: drupal_http_request should return error if reaches max allowed
+    // redirects
+    if (!isset($result->error) || !in_array($result->code, array(301, 302, 307))) {
+
+      // 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);
