I'm currently testing an OpenID implementation, and I'm noticing that Google sends a different identifier for different consuming host name / domain name, even for the same user. For example, Google sends a different identifier when the requesting site is localhost
, compared to the identifier they send when the requesting site is 127.0.0.1
for the same user.
Note: I haven't actually tested this using public domain names, but I can't see why the behavior would be any different.
My concern with Google's behavior is that if we ever choose to change our website domain name in the future, then users will no longer be able to log in to开发者_Go百科 the website using Google's OpenId as the identity provider. This seems to be a big problem. Am I missing something, or are all OpenID consuming sites faced with this potential problem?
I've also tested this with MyOpenId, but the identifier that MyOpenId creates is fixed, so this wouldn't be a problem with them.
Have a look at Google OpenID most important technical issue. Some infos there. Basically a link taken from the accounts section of stackoverflow.com ;)
-sa
It appears that the OpenID URLs returned by Google depend on the openid.realm
value that is used. Also, I just tried the OpenID process with a realm set to http://MYREALM
and openid.return_to
set to http://localhost/openid.php
, but received an HTTP 400 Bad Request. Apparently, Google checks that the realm has the same domain (and probably port) as the "return to" URL.
One idea for a work-around is to store the Gmail address associated with the OpenID. Whenever you request a Google OpenID, always request the user's email address via Attribute Exchange's http://axschema.org/contact/email
type. If you ever change domains, you can associate the new OpenID URL with their account based on the email address.
Note: It is imperative that you verify the HMAC-SHA1 signature. Otherwise, anyone would be able to "return to" your web application's OpenID checkauth action with a constructed email address, allowing them to take over someone's account if they know the target's Gmail address.
When a user is logging in with their Google Account for the first time after the switch, the migration procedure is:
Send a POST request to
https://www.google.com/accounts/o8/ud
with the following parameters:+---------------------+----------------------------------+ | openid.ns | http://specs.openid.net/auth/2.0 | | openid.mode | associate | | openid.assoc_type | HMAC-SHA1 | | openid.session_type | no-encryption | +---------------------+----------------------------------+
(replace
openid.realm=http://NEWREALM
as appropriate)The response will be something like:
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
With the redirect to the Service URI,
https://www.google.com/accounts/o8/ud
, mode 'checkid_setup', make sure to send the assoc_handle that was previously obtained as well as require the user's email address via Attribute Exchange. In other words, be sure to send the following, additional parameters:+----------------------+----------------------------------------------------------+ | 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 | +----------------------+----------------------------------------------------------+
The "return to" request will include the important parameters
openid_signed
,openid_sig
, andopenid_ext1_value_email
.- Follow the OpenID Authentication 2.0 Specification's procedure for generating the signature. If the base64-encoding of the HMAC-SHA1 signature is not the same as the
openid_sig
value, then the signature is invalid. Note that the MAC key in this example isF5XUXvoYutLvFv4IzJS0diytLmbe
. Use whatever Google's server sent back with the association request.
Google's Federated Login documentation page states that http://axschema.org/contact/email
"[r]equests the user's gmail address". Presumably, once a Google Account is created then the "Gmail" email address is fixed. But, if this assumption is not valid, then it is not safe to use this procedure because a malicious user could change their email address as returned by the Federated Login Service to whatever the email address is of the account that they wish to steal.
Just to be on the safe side, before activating the new OpenID, send an email verification request to the email address. The verification link would contain a nonce associated with the new OpenID. Once the link is clicked, the new OpenID would be fully associated with the user's account as receipt of the nonce would verify the association between email address and new OpenID URL.
See also: openid.sig -- How is it generated?
There is another possible work-around. When making the indirect authentication request (redirecting to the Service URI), send the old OpenID URL as the values of the openid.claimed_id
and openid.identity
parameters even though realm is set to the new realm.
On my developer machine, I have the domain 'thiscomputer' aliased to 127.0.0.1. When I requested authentication from Google's OpenID Provider, realm 'http://thiscomputer' and openid.identity
and openid.claimed_id
both set to http://specs.openid.net/auth/2.0/identifier_select
, I got back something like:
https://www.google.com/accounts/o8/id?id=VGwSBXN7Q00X4G9CTAsLPMJ3m6JaPljpkrURAUZJ
I then requested authentication from the OP, realm 'http://localhost' and openid.identity
and openid.claimed_id
both set to http://specs.openid.net/auth/2.0/identifier_select
. I got back something like:
https://www.google.com/accounts/o8/id?id=VGwSBXNwzPQk-puNdfZl4tP-s7JNHPA3WmMHozHJ
I then requested authentication from the OP, realm 'http://localhost' and openid.identity
and openid.claimed_id
both set to https://www.google.com/accounts/o8/id?id=VGwSBXN7Q00X4G9CTAsLPMJ3m6JaPljpkrURAUZJ
(the OpenID identity for my Google Account when realm is 'http://thiscomputer'). I got back:
https://www.google.com/accounts/o8/id?id=VGwSBXN7Q00X4G9CTAsLPMJ3m6JaPljpkrURAUZJ
That is, I got back the same OpenID identity URL as when realm is 'http://thiscomputer'. Thus, even though I "migrated" my OpenID-relying web app from 'thiscomputer' to 'localhost', I can still use the old OpenID identity URL.
This solution works as long as you know the user's old OpenID identity URL, perhaps because it is stored in a cookie.
One note: I tried setting openid.identity
and openid.claimed_id
to different values (e.g. one is http://specs.openid.net/auth/2.0/identifier_select
while the other is https://www.google.com/accounts/o8/id?id=VGwSBXN7Q00X4G9CTAsLPMJ3m6JaPljpkrURAUZJ
or one is https://www.google.com/accounts/o8/id?id=VGwSBXN7Q00X4G9CTAsLPMJ3m6JaPljpkrURAUZJ
and the other is https://www.google.com/accounts/o8/id?id=VGwSBXNwzPQk-puNdfZl4tP-s7JNHPA3WmMHozHJ
), but Google's OP service responded with "The page you requested is invalid."
精彩评论