Page MenuHomePhabricator

Handle central user IDs in AuthManager
Closed, ResolvedPublic

Description

Some auth extensions can provide central user IDs which are the same over a wiki farm (e.g. CentralAuth's globaluser.gu_id). Some extensions need a global id when installed on a wiki farm (e.g. OAuth so a tool you authorized on one wiki can edit in your name on another). Currently there is no clean way to communicate these IDs - OAuth for example provides a bunch of hooks like OAuthGetLocalUserFromCentralId and OAuthGetCentralIdFromUserName and CentralAuth implements them. This is not a great solution - every centralid-relying extension providing a set of hooks and every auth extension implementing all of them wouldn't scale well. It would be nice if AuthManager provided a mechanism through which this communitaction can be channeled.

AuthManager::getCentralIdFromUser( $user, $providerId ) and AuthManager::getUserFromCentralId( $id, $providerId ) would be a simple way to provide this.

Event Timeline

Tgr raised the priority of this task from to Needs Triage.
Tgr updated the task description. (Show Details)
Tgr subscribed.

The more I think about this, the more I think it doesn't really work in AuthManager.

First, I have no idea why there's a "$providerId" in the suggested methods. The caller has to know what providers are available? That doesn't make sense.

At first glance, it seems this could fit well in AuthManager: AuthManager could iterate through the PrimaryAuthenticationProviders until one returned an ID, then somehow munge it to avoid collisions between providers, and there you go. But then what happens if an earlier provider suddenly gains knowledge of the user? The supposedly-constant central ID for that user changes!

So maybe this would be better done in some other way, in which case it doesn't need to be waiting for AuthManager. The only question is where to put it. User is tempting, although User already has so much in it that I'm hesitant to add more, even though it's really the best fit if we don't want to create some sort of "CentralIdService" class. Whichever way, the implementation may be as simple as copying getCentralUserNameFromId, getLocalUserFromCentralId, getCentralIdFromLocalUser, and getCentralIdFromUserName out of OAuth's MWOAuthUtils.

The status quo is that you need to tell OAuth via a site config option to use CentralAuth as an identity source, and CentralAuth needs to implement the four OAuth hooks. If we wanted to use another auth extension as the source, it would also need to implement those hooks; if we wanted to add a new identity consumer extension, we would need a new set of hooks.

AuthManager::getCentralIdFromUser( $user, $providerId ) preserves the aspect that you need to manually configure which auth provider to use as the source, but removes the need for the mess with the hooks - providers just need to expose a central ID, and consumers just need to call getCentralIdFromUser. That's a pretty clear improvement.

A central id service would actually fit into this framework - it would just be another "provider" which would not implement any methods in a nontrivial way except the one returning the central ID. You could then make getCentralIdFromUser( $user ) default to getCentralIdFromUser( $user, 'CentralIdService' ).

That said, such a central id service would be rather complicated. For example, if the user registers to wiki A with a Facebook account, then to wiki B with a Google account, then links his Google account on wiki A, you will initially have to distinct central IDs which you need to merge once the system becomes aware that it is the same user (and as an implication, the central IDs would not be constant and you would probably have to implement the kind of id update hooks UserMerge has). I would rather go for the simple solution and then we can later built the complex one on top of it if we really see the need.

Change 254300 had a related patch set uploaded (by Anomie):
Add a central ID lookup service

https://gerrit.wikimedia.org/r/254300

Change 254302 had a related patch set uploaded (by Anomie):
Implement CentralIdLookup for CentralAuth

https://gerrit.wikimedia.org/r/254302

Change 254300 merged by jenkins-bot:
Add a central ID lookup service

https://gerrit.wikimedia.org/r/254300

Change 254302 merged by jenkins-bot:
Implement CentralIdLookup for CentralAuth

https://gerrit.wikimedia.org/r/254302

Anomie claimed this task.

Not "in AuthManager", but it can be handled in core now which is close enough.