Claimed Identity feature was enabled to support old Google OpenID
accounts, that cannot be activated anymore. In some corner cases,
when for example the URL is not from the production Gerrit site,
like it's always the case on staging instance, the OpenID identity
may deviate from the original one. In case of mismatch, the lookup
for real user for the claimed identity would fail, and the linking
mode is lost, and as the consequence a new account is created.
Creating new account, when user asked for linking is always the
worst option we have, as this cannot be easily undone. Detect this
case, preserve the linking mode and keep trying to link instead of
create new account. Note that in case this account already exist,
the linking would fail with the sane message.
Test Plan I:
1. Create gerrit site gerrit.example.org in year 2010
2. Configure the site to use OpenId (non SSO mode)
3. Observe that 85% user base using Google OpeID
4. After Google's OpenID shutdown in May 2015, nobody is able
to login anymore using their account and link their identity
primary to Launchpad
5. Swap production site to staging site with entire database
and Git repository
6. Install gerrit-oauth-provider plugin and activate automagically
Google OpenID old token discovery and linking option
7. Configure new OAuth application on Google developer console, but
route it to gerrit-test.example.org. Note that this deviation breaks
the old OpenID tokens!
8. Test with old user, that has OpenID Google account, that was
additionally linked to Launchpad OpenID provider
9. Login with Launchpad OpenID iendtity for this user
10. Profile=>Setting=>Link another identity
11. Select Google OAuth provider offered by the gerrit-oauth-provider
plugin
12. Intead of linking to the existing account (or linking error) new
account is created
13. This diff fixed this. Error is issued, that the account already
exist and linking is not possible
Note that when all this would be done on real production site, this
error wouldn't happen, because the URL wouldn't deviate and there
wouldn't be token mismatch between OpenID token in the database and the
token discovered by Google's OAuth OpenID scope. But still, we could
easily prevent in this very specific corner case the creation of new
account.
Note that it's still possible with this setting to create duplicate
account for this user by signing in directly with Google OAuth provider
without linking mode. However, this would also work as expected on the
real production site, because old OpenID token would match with the
existing Gerrit account and linking would happen automagically. That is
exactly why the option link-to-existing-openid-accounts = true was
invented. Unfortunately there is no way to test that this work as
expected already on staging Gerrit instance.
Test Plan II:
1. User register first time after Google's OpenID 2.0 shut down with
OpenID provider, say Launchpad
2. Login with Launchpad
3. Profile=>Setting=>Link another identity
4. Link with Google OAuth2 provider
Expected: The OAuth2 identity is linked to the existing account.
Actual: New account is created.
This diff fixed it. The problem is that I apparently misunderstood
the migration spec: [1] and assumed that the OpenID token is provided
only when a user was already associated with this site. This is
not true. OpenID token also returned for new users, that were never
registered with this site before. To rectify it, and still to work
for both, known and unknown users, we apply the check. If the OpenID
token is known use it for linking. If it is not known, ignore it, but
preserve linking mode.
* [1] https://developers.google.com/identity/protocols/OpenID2Migration#map-identifiers
Change-Id: Icf70cde5fd96cd72aa383218e1d143107a551b45