我目前正在测试一个OpenID实现,我注意到Google为不同的消费主机名/域名发送了不同的标识符,即使对于同一个用户也是如此。例如,Google在请求网站为localhost
时发送了不同的标识符,与请求网站为同一用户127.0.0.1
时发送的标识符相比较。
注意:我实际上并没有使用公共域名对此进行测试,但我不明白为什么行为会有所不同。
我对Google行为的担忧是,如果我们以后选择更改我们的网站域名,那么用户将无法再使用Google的OpenId作为身份提供商登录该网站。这似乎是一个大问题。我错过了什么,或者所有OpenID消费网站都遇到了这个潜在的问题?
我也用MyOpenId对此进行了测试,但是MyOpenId创建的标识符是固定的,所以这对他们来说不是问题。
答案 0 :(得分:5)
看看Google OpenID most important technical issue。那里有一些信息。基本上是从stackoverflow.com的帐户部分获取的链接;)
-sa
答案 1 :(得分:3)
Google返回的OpenID网址似乎取决于所使用的openid.realm
值。此外,我刚刚尝试了OpenID进程,其域设置为http://MYREALM
,openid.return_to
设置为http://localhost/openid.php
,但收到了HTTP 400错误请求。显然,Google会检查域名与“返回”网址具有相同的域名(可能还有端口)。
解决方法的一个想法是存储与OpenID相关联的Gmail地址。每当您申请Google OpenID时,请始终通过Attribute Exchange的http://axschema.org/contact/email
类型请求用户的电子邮件地址。如果您更改了域名,则可以根据电子邮件地址将新的OpenID URL与其帐户相关联。
注意:验证HMAC-SHA1签名是强制性。否则,任何人都可以使用构建的电子邮件地址“返回”您的Web应用程序的OpenID checkauth操作,如果他们知道目标的Gmail地址,则允许他们接管某个人的帐户。
当用户首次使用Google帐户登录时,迁移过程为:
使用以下参数向https://www.google.com/accounts/o8/ud
发送POST请求:
+---------------------+----------------------------------+ | openid.ns | http://specs.openid.net/auth/2.0 | | openid.mode | associate | | openid.assoc_type | HMAC-SHA1 | | openid.session_type | no-encryption | +---------------------+----------------------------------+
(视情况更换openid.realm=http://NEWREALM
)
响应类似于:
ns:http://specs.openid.net/auth/2.0 session_type:no-encryption assoc_type:HMAC-SHA1 assoc_handle:B5hJNa39Cl39BXSOKMqkPpk03rJmE0GI6EhHBkvfLOBFAMMQX67HjuFq expires_in:46800 mac_key:F5XUXvoYutLvFv4IzJS0diytLmbe
通过重定向到服务URI https://www.google.com/accounts/o8/ud
,模式'checkid_setup',确保发送之前获得的assoc_handle,并通过Attribute Exchange要求用户的电子邮件地址。换句话说,请务必发送以下附加参数:
+----------------------+----------------------------------------------------------+ | openid.assoc_handle | B5hJNa39Cl39BXSOKMqkPpk03rJmE0GI6EhHBkvfLOBFAMMQX67HjuFq | | openid.ns.ax | http://openid.net/srv/ax/1.0 | | openid.ax.mode | fetch_request | | openid.ax.type.email | http://axschema.org/contact/email | | openid.ax.required | email | +----------------------+----------------------------------------------------------+
“返回”请求将包含重要参数openid_signed
,openid_sig
和openid_ext1_value_email
。
openid_sig
值不同,则签名无效。请注意,此示例中的MAC密钥为F5XUXvoYutLvFv4IzJS0diytLmbe
。使用Google的服务器通过关联请求发回的任何内容。
Google's Federated Login documentation page states http://axschema.org/contact/email
“[r]请求用户的Gmail地址”。据推测,一旦创建了Google帐户,就会修复“Gmail”电子邮件地址。但是,如果此假设无效,则使用此过程是不安全的,因为恶意用户可以将联合登录服务返回的电子邮件地址更改为他们希望窃取的帐户的电子邮件地址。 / p>
为了安全起见,在激活新的OpenID之前,请向电子邮件地址发送电子邮件验证请求。验证链接将包含与新OpenID相关联的随机数。单击链接后,新的OpenID将与用户的帐户完全关联,因为收到nonce将验证电子邮件地址与新OpenID URL之间的关联。
答案 2 :(得分:1)
还有另一种可能的解决方法。在进行间接身份验证请求(重定向到服务URI)时,将旧 OpenID URL作为openid.claimed_id
和openid.identity
参数的值发送,即使域设置为新领域。
在我的开发者计算机上,我将域名'thiscomputer'别名为127.0.0.1。当我向Google的OpenID提供商请求身份验证时,域名'http:// thiscomputer'以及openid.identity
和openid.claimed_id
都设置为http://specs.openid.net/auth/2.0/identifier_select
,我得到了类似的内容:
https://www.google.com/accounts/o8/id?id=VGwSBXN7Q00X4G9CTAsLPMJ3m6JaPljpkrURAUZJ
然后我请求来自OP的身份验证,领域'http:// localhost'和openid.identity
以及openid.claimed_id
都设置为http://specs.openid.net/auth/2.0/identifier_select
。我得到了类似的东西:
https://www.google.com/accounts/o8/id?id=VGwSBXNwzPQk-puNdfZl4tP-s7JNHPA3WmMHozHJ
然后我请求来自OP的身份验证,域名'http:// localhost'和openid.identity
以及openid.claimed_id
都设置为https://www.google.com/accounts/o8/id?id=VGwSBXN7Q00X4G9CTAsLPMJ3m6JaPljpkrURAUZJ
(当域名是我的Google帐户的OpenID身份时的 'http:// thiscomputer')。我回来了:
https://www.google.com/accounts/o8/id?id=VGwSBXN7Q00X4G9CTAsLPMJ3m6JaPljpkrURAUZJ
也就是说,我获得了与realm为'http:// thiscomputer'时相同的OpenID身份URL。因此,即使我将依赖OpenID的Web应用程序从“thiscomputer”“迁移”到“localhost”,我仍然可以使用旧的OpenID身份URL。
只要您知道用户的旧OpenID身份URL,此解决方案就可以正常工作,可能是因为它存储在cookie中。
一个注意事项:我尝试将openid.identity
和openid.claimed_id
设置为不同的值(例如,一个为http://specs.openid.net/auth/2.0/identifier_select
,而另一个为https://www.google.com/accounts/o8/id?id=VGwSBXN7Q00X4G9CTAsLPMJ3m6JaPljpkrURAUZJ
或一个为https://www.google.com/accounts/o8/id?id=VGwSBXN7Q00X4G9CTAsLPMJ3m6JaPljpkrURAUZJ
,另一个是https://www.google.com/accounts/o8/id?id=VGwSBXNwzPQk-puNdfZl4tP-s7JNHPA3WmMHozHJ
),但Google的OP服务回复“您请求的页面无效。”