Page MenuHomePhabricator

Local-account creation fails with LDAP Authentication
Open, LowestPublic

Description

I'm running MediaWiki 1.30.0 with the latest version of LDAP Authentication extension (master branch, commit aa165265357f0420ae8f17e5b8bd7e80f8febe79)
I need to support LDAP accounts and local accounts (MySQL), so I configured

$wgLDAPUseLocal = true;

which basically works, but I'm unable to create new local accounts at Special:CreateAccount...
As soon as I enter a user name (and leave the input field) a red box appears saying

Username entered already in use. Please choose a different name.

In the web developer toolbar, I can see a get request to WIKIBASE/api.php?action=query&format=json&list=users&ususers=blah23&usprop=cancreate&formatversion=2&errorformat=html&errorsuselocal=true&uselang=en -> I cannot see the selected domain here!?
(Not sure if that is already a bug? How is the API endpoint supposed to know under which domain I want to create the account? But maybe only local is supported and the domain-drop-down on that page is irrelevant?)

I ignore the message and nevertheless submit the form, the browser sends a POST request containing all the data (incl. domain):

wpName	blah23
wpPassword	test
wpDomain	local
retype	test
email	
realname	
reason	
wpCreateaccount	Create+account
wpEditToken	xxxx
title	Special:CreateAccount
authAction	create
force	
wpCreateaccountToken	xxxx

But it still says Username entered already in use. Please choose a different name. ...
So it seems as I cannot create a new local account...!?
If I disable the LDAP Authentication extension, the same POST request (just pressing F5 then) is working fine and a new account is being created..

Debugging

I already went a bit through the code, and if I understand correctly the check for existing users basically starts at AuthManager.php -> beginAccountCreation( User $creator, array $reqs, $returnToUrl ), where I can see it gets the domain in $reqs.
On line 1068 it then calls AuthManager.php -> canCreateAccount( $username, $options), which only retrieves the username:

		$status = $this->canCreateAccount(
			$username, [ 'flags' => User::READ_LOCKING, 'creating' => true ]
		);

From canCreateAccount (line 943) the function AuthManager.php -> userExists ($username, $flags) is called, which then iterates getPrimaryAuthenticationProviders () to testUserExists..

Arriving at AuthPluginPrimaryAuthenticationProvider.php -> testUserExists( $username, $flags = User::READ_NORMAL ), it simply iterates every domain (as the domain information has been lost above) and checks the AuthPlugin::userExists():

		foreach ( $domains as $domain ) {
			$this->auth->setDomain( $domain );
			if ( $this->auth->userExists( $username ) ) {
				$this->auth->setDomain( $curDomain );
				return true;
			}
		}

The LDAP Authentication extension in my case then always returns true (=user exists), as it cannot add LDAP users ([[ https://github.com/wikimedia/mediawiki-extensions-LdapAuthentication/blob/master/LdapAuthenticationPlugin.php#L497 | AddLDAPUsers is false]]). So even if I would introduce an (in my opinion) missing check for 'local' == $this->getDomain() at the LdapAuthentication extension, it will still fail, as AuthPluginPrimaryAuthenticationProvider.php -> testUserExists still checks for all domains (including LDAP domains..).

Workaround

As explained above, one option would be to temporarily disable LDAP Authentication.
Another option is to create a new local account with a command line call for eg.

php maintenance/createAndPromote.php USER PASS

which apparently doesn't check all these things..

However, I don't want to grant command line access to the users/maintainers of the wiki.

Solution

Does anyone have an idea how to fix that issue?
I'm not sure, but I guess the AuthManager.php -> canCreateAccount( $username, $options) should also know about the domain, in which the user should be created? And then also provide this information to AuthPluginPrimaryAuthenticationProvider.php -> testUserExists( $username, $flags = User::READ_NORMAL ), which doesn't check the LDAP extension for local accounts (or provides the domain to the LDAP extension, which then knows where/what/if to check..)?

Event Timeline

Vvjjkkii renamed this task from Local-account creation fails with LDAP Authentication to ambaaaaaaa.Jul 1 2018, 1:05 AM
Vvjjkkii triaged this task as High priority.
Vvjjkkii updated the task description. (Show Details)
Vvjjkkii removed a subscriber: Aklapper.
CommunityTechBot renamed this task from ambaaaaaaa to Local-account creation fails with LDAP Authentication.Jul 1 2018, 9:11 PM
CommunityTechBot raised the priority of this task from High to Needs Triage.
CommunityTechBot updated the task description. (Show Details)
CommunityTechBot added a subscriber: Aklapper.

Hi

Please confirm that the issue "Local-account creation fails with LDAP Authentication " has been resolved.

I clone the latest version but still face with the issue.

Please advise. Thanks

@TrunhHuynh: Please see in the upper left corner that this task is "Open" and hence it is not resolved. Your patches are welcome if you fancy playing with code.

Unfortunately this has not been resolved yet. As a workaround you can modiy https://github.com/wikimedia/mediawiki-extensions-LDAPProvider/blob/6ce932dd2a91d974bbd2d8cf71bfa53d6eca1a58/src/UserDomainStore.php#L27-L28 and just add

	public function getDomainForUser( User $user ) {
                return '<whatever-domain-you-have-configured>';
		$userId = $user->getId();

EDIT: Please ignore my reply. I just noticed that this is not related to LDAP-Stack extensions LDAPProvider and LDAPAuthorization