Page MenuHomePhabricator

TypeError when logging via LDAPProvider/PluggableAuth/LDAPAuthentication2
Open, Needs TriagePublicBUG REPORT

Description

Steps to replicate the issue (include links if applicable):
I've installed MediaWiki 1.38.2 and imported extensions LDAPProvider, PluggableAuth and LDAPAuthentication2. I've configured the ldap.json file to point to my Active Directory instance and I can see via tcpdumps that it is connecting with the bind user and retrieving data for the user I'm trying to login. If I login with a bad user/password I get the standard error about credentials not being found. If I login with an actual user account I'm getting the error listed below.

I've included a snippet of my LocalSettings.php:

# End of automatically generated settings.
# Add more configuration options below.
$wgGroupPermissions['*']['autocreateaccount'] = true;
$wgGroupPermissions['*']['createaccount'] = true;

wfLoadExtension( 'LDAPProvider' );
$LDAPProviderDomainConfigs = "/var/www/ldap.json";

wfLoadExtension( 'PluggableAuth' );
wfLoadExtension( 'LDAPAuthentication2' );

$wgShowExceptionDetails = true;

What happens?:

MediaWiki internal error.

Original exception: [d09fd36bad55cb350eed6fb8] /index.php?title=Special:PluggableAuthLogin TypeError: Return value of User::getName() must be of the type string, null returned
Backtrace:
from /var/www/mediawiki-1.38.2/includes/user/User.php(1922)
#0 /var/www/mediawiki-1.38.2/includes/user/User.php(1405): User->getName()
#1 /var/www/mediawiki-1.38.2/includes/user/User.php(1741): User->getBlockedStatus()
#2 /var/www/mediawiki-1.38.2/includes/block/BlockManager.php(546): User->getBlock()
#3 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(787): MediaWiki\Block\BlockManager->trackBlockWithCookie()
#4 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(647): MediaWiki::preOutputCommit()
#5 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(935): MediaWiki->doPreOutputCommit()
#6 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(563): MediaWiki->main()
#7 /var/www/mediawiki-1.38.2/index.php(53): MediaWiki->run()
#8 /var/www/mediawiki-1.38.2/index.php(46): wfIndexMain()
#9 {main}

Exception caught inside exception handler: [d09fd36bad55cb350eed6fb8] /index.php?title=Special:PluggableAuthLogin TypeError: Return value of User::getName() must be of the type string, null returned
Backtrace:
from /var/www/mediawiki-1.38.2/includes/user/User.php(1922)
#0 /var/www/mediawiki-1.38.2/includes/user/User.php(3125): User->getName()
#1 /var/www/mediawiki-1.38.2/includes/skins/SkinTemplate.php(100): User->getUserPage()
#2 /var/www/mediawiki-1.38.2/includes/skins/SkinMustache.php(54): SkinTemplate->setupTemplateContext()
#3 /var/www/mediawiki-1.38.2/skins/Vector/includes/SkinVector.php(455): SkinMustache->generateHTML()
#4 /var/www/mediawiki-1.38.2/includes/skins/SkinTemplate.php(150): Vector\SkinVector->generateHTML()
#5 /var/www/mediawiki-1.38.2/includes/OutputPage.php(2807): SkinTemplate->outputPage()
#6 /var/www/mediawiki-1.38.2/includes/exception/MWExceptionRenderer.php(157): OutputPage->output()
#7 /var/www/mediawiki-1.38.2/includes/exception/MWExceptionRenderer.php(76): MWExceptionRenderer::reportHTML()
#8 /var/www/mediawiki-1.38.2/includes/exception/MWExceptionHandler.php(107): MWExceptionRenderer::output()
#9 /var/www/mediawiki-1.38.2/includes/exception/MWExceptionHandler.php(202): MWExceptionHandler::report()
#10 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(585): MWExceptionHandler::handleException()
#11 /var/www/mediawiki-1.38.2/index.php(53): MediaWiki->run()
#12 /var/www/mediawiki-1.38.2/index.php(46): wfIndexMain()
#13 {main}

What should have happened instead?:

Software version (skip for WMF-hosted wikis like Wikipedia):
mediawiki-1.38.2
LDAPProvider: master, 2022-07-22T16:10:53, 80f8cc8
PluggableAuth: REL1_35,2022-05-23T20:18:19,e2589cd
LDAPAuthentication2: master,2022-07-22T09:10:14,6bc5848

Other information (browser name/version, screenshots, etc.):
I tried running:

duckofdeath@wikiserver:/var/www/mediawiki$ sudo php extensions/LDAPProvider/src/UserInfoRequest.php --domain example.com --user duckofdeath
duckofdeath@wikiserver:/var/www/mediawiki$ echo $?
0

But there is nothing printed to the command line, is that normal?

ldap.json below:

{
  "example.com": {
    "connection": {
      "server": "ad.example.com",
      "port": "3268",
      "user": "CN=srv_wikiauth,OU=Service Accounts,OU=Accounts,DC=example,DC=com",
      "pass": "<redacted>",
      "enctype": "clear",
      "options": {
        "LDAP_OPT_DEREF": 1
      },
      "basedn": "DC=corp,DC=example,DC=com",
      "userbasedn": "OU=Accounts,DC=corp,DC=example,DC=com",
      "groupbasedn": "OU=Groups,DC=corp,DC=example,DC=com",
      "searchattribute": "SamAccountName",
      "usernameattribute": "SamAccountName",
      "realnameattribute": "cn",
      "emailattribute": "mail",
      "grouprequest": "MediaWiki\\Extension\\LDAPProvider\\UserGroupsRequest\\UserMemberOf::factory",
      "presearchusernamemodifiers": [ "lowercase" ]
    },
    "userinfo": [],
    "authorization": [],
    "groupsync": {
      "mapping": {
        "sysop": "CN=SuperFriends,OU=Restricted,OU=Groups,DC=corp,DC=example,DC=com"
      }
    }
  }
}

Edit: Note that /var/www/wikimedia is a symbolic link to /var/www/wikimedia-1.38.2

Event Timeline

Can you try replacing SamAccountName with the proper capitalization (sAMAccountName)?

Thanks taavi, I replaced the words in my ldap.json:

sudo grep sAMAccountName ldap.json
      "searchattribute": "sAMAccountName",
      "usernameattribute": "sAMAccountName",

But I am getting the same error message as before.

Hi,

I won't presume that you have seen this page, but it includes a working sample.
https://www.mediawiki.org/wiki/Manual:Active_Directory_Integration

Your JSON config looks (almost) fine...

  • use the capitalisation as seen in the Tune LocalSettings.php code block, for your "searchattribute" and "usernameattribute"
  • lowercase is fine, as seen in the code-block

Most importantly, install ALL of the extensions then bootstrap them as below. Skipping any of them will result in failure... given your setup with AD.

Extension:LDAPAuthorization
Extension:LDAPAuthentication2
Extension:LDAPGroups
Extension:LDAPProvider
Extension:LDAPUserInfo
Extension:PluggableAuth

Sample:

php
// general prep
$wgEmailConfirmToEdit = false;
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['sysop']['createaccount'] = false;
$wgGroupPermissions['*']['autocreateaccount'] = true;
$wgBlockDisablesLogin = true;

// load all extensions
wfLoadExtension( 'PluggableAuth' );
wfLoadExtension( 'LDAPProvider' );
wfLoadExtension( 'LDAPAuthentication2' );
wfLoadExtension( 'LDAPAuthorization' );
wfLoadExtension( 'LDAPUserInfo' );
wfLoadExtension( 'LDAPGroups' );

// load JSON config
$LDAPProviderDomainConfigs = $LDAPProviderDomainConfigs;

I'm pretty certain that LDAPUserInfo is the missing piece of your puzzle, but you should load the whole lot for ease.

After setting up the config, please don't forget to run update.php just in case some schema changes are needed. I would not be surprised, if you didn't load all the modules yet and run update.php shortly after.

Thanks @nick_parrott,

Your JSON config looks (almost) fine...

use the capitalisation as seen in the Tune LocalSettings.php code block, for your "searchattribute" and "usernameattribute"
lowercase is fine, as seen in the code-block

I think it was the "Prepare ldap.json" block where the search/username attributes appear but I've changed them to:

duckofdeath@wikiserver:/var/www/mediawiki# grep attribute ../ldap.json
      "searchattribute": "samaccountname",
      "usernameattribute": "samaccountname",
      "realnameattribute": "cn",
      "emailattribute": "mail",

Most importantly, install ALL of the extensions then bootstrap them as below. Skipping any of them will result in failure... given your setup with AD.

Extension:LDAPAuthorization
Extension:LDAPAuthentication2
Extension:LDAPGroups
Extension:LDAPProvider
Extension:LDAPUserInfo
Extension:PluggableAuth

I've got them all untarred and I ran update.php after:

duckofdeath@wikiserver:/var/www/mediawiki# ls -l extensions/ | grep "LDAP\|Plugg"
drwxr-xr-x  6  498  498 4096 Jul 22 03:10 LDAPAuthentication2
drwxr-xr-x  6  498  498 4096 Jul  4 00:13 LDAPAuthorization
drwxr-xr-x  7  498  498 4096 Jul  6 00:12 LDAPGroups
drwxr-xr-x 10  498  498 4096 Jul 22 10:10 LDAPProvider
drwxr-xr-x  5  498  498 4096 May 22 18:14 LDAPUserInfo
drwxr-xr-x  4  498  498 4096 May 23 14:18 PluggableAuth

My LocalSettings.php matches pretty closely to the sample:

# End of automatically generated settings.
# Add more configuration options below.
$wgEmailConfirmToEdit = false;
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['sysop']['createaccount'] = false;
$wgGroupPermissions['*']['autocreateaccount'] = true;
$wgBlockDisablesLogin = true;


wfLoadExtension( 'PluggableAuth' );
wfLoadExtension( 'LDAPProvider' );
wfLoadExtension( 'LDAPAuthentication2' );
wfLoadExtension( 'LDAPAuthorization' );
wfLoadExtension( 'LDAPUserInfo' );
wfLoadExtension( 'LDAPGroups' );

$LDAPProviderDomainConfigs = "/var/www/ldap.json";

$wgShowExceptionDetails = true;

Unfortunately, I'm still getting the same error:

MediaWiki internal error.

Original exception: [b988826a2092d6874933ed4f] /index.php?title=Special:PluggableAuthLogin TypeError: Return value of User::getName() must be of the type string, null returned
Backtrace:
from /var/www/mediawiki-1.38.2/includes/user/User.php(1922)
#0 /var/www/mediawiki-1.38.2/extensions/LDAPAuthorization/src/Hook/PluggableAuthUserAuthorization.php(86): User->getName()
#1 /var/www/mediawiki-1.38.2/extensions/LDAPAuthorization/src/Hook/PluggableAuthUserAuthorization.php(78): MediaWiki\Extension\LDAPAuthorization\Hook\PluggableAuthUserAuthorization->process()
#2 /var/www/mediawiki-1.38.2/includes/HookContainer/HookContainer.php(338): MediaWiki\Extension\LDAPAuthorization\Hook\PluggableAuthUserAuthorization::callback()
#3 /var/www/mediawiki-1.38.2/includes/HookContainer/HookContainer.php(137): MediaWiki\HookContainer\HookContainer->callLegacyHook()
#4 /var/www/mediawiki-1.38.2/includes/Hooks.php(137): MediaWiki\HookContainer\HookContainer->run()
#5 /var/www/mediawiki-1.38.2/extensions/PluggableAuth/includes/PluggableAuthLogin.php(53): Hooks::run()
#6 /var/www/mediawiki-1.38.2/includes/specialpage/SpecialPage.php(671): PluggableAuthLogin->execute()
#7 /var/www/mediawiki-1.38.2/includes/specialpage/SpecialPageFactory.php(1378): SpecialPage->run()
#8 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(315): MediaWiki\SpecialPage\SpecialPageFactory->executePath()
#9 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(912): MediaWiki->performRequest()
#10 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(563): MediaWiki->main()
#11 /var/www/mediawiki-1.38.2/index.php(53): MediaWiki->run()
#12 /var/www/mediawiki-1.38.2/index.php(46): wfIndexMain()
#13 {main}

Exception caught inside exception handler: [b988826a2092d6874933ed4f] /index.php?title=Special:PluggableAuthLogin TypeError: Return value of User::getName() must be of the type string, null returned
Backtrace:
from /var/www/mediawiki-1.38.2/includes/user/User.php(1922)
#0 /var/www/mediawiki-1.38.2/includes/user/User.php(3125): User->getName()
#1 /var/www/mediawiki-1.38.2/includes/skins/SkinTemplate.php(100): User->getUserPage()
#2 /var/www/mediawiki-1.38.2/includes/skins/SkinMustache.php(54): SkinTemplate->setupTemplateContext()
#3 /var/www/mediawiki-1.38.2/skins/Vector/includes/SkinVector.php(455): SkinMustache->generateHTML()
#4 /var/www/mediawiki-1.38.2/includes/skins/SkinTemplate.php(150): Vector\SkinVector->generateHTML()
#5 /var/www/mediawiki-1.38.2/includes/OutputPage.php(2807): SkinTemplate->outputPage()
#6 /var/www/mediawiki-1.38.2/includes/exception/MWExceptionRenderer.php(157): OutputPage->output()
#7 /var/www/mediawiki-1.38.2/includes/exception/MWExceptionRenderer.php(76): MWExceptionRenderer::reportHTML()
#8 /var/www/mediawiki-1.38.2/includes/exception/MWExceptionHandler.php(107): MWExceptionRenderer::output()
#9 /var/www/mediawiki-1.38.2/includes/exception/MWExceptionHandler.php(202): MWExceptionHandler::report()
#10 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(585): MWExceptionHandler::handleException()
#11 /var/www/mediawiki-1.38.2/index.php(53): MediaWiki->run()
#12 /var/www/mediawiki-1.38.2/index.php(46): wfIndexMain()
#13 {main}

I've just stumbled across https://www.mediawiki.org/wiki/Manual:How_to_debug/Login_problems and I'll work my way through that to see if I can figure out what's coming back from the LDAP server, etc.

I'm also considering blowing away the install and starting again, perhaps the half-installed extensions caused an issue with the account creation.

Some interesting things from the debug log:

$wgDebugLogFile = "/var/log/mediawiki/debug-{$wgDBname}.log";
[PluggableAuth] Getting PluggableAuth singleton
[PluggableAuth] Class name: MediaWiki\Extension\LDAPAuthentication2\PluggableAuth
[session] SessionBackend "b47afpmte0jl9d8p7mf4cp2mkifnmu67" data dirty due to dirty(): MediaWiki\Extension\LDAPAuthentication2\PluggableAuth->checkLDAPLogin/MediaWiki\Auth\AuthManager->setAuthenticationSessionData/MediaWiki\Session\Session->setSecret/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[LDAPProvider] Setting LDAP_OPT_PROTOCOL_VERSION to 3
[LDAPProvider] Setting LDAP_OPT_REFERRALS to 0
[LDAPProvider] Setting LDAP_OPT_DEREF to 1
[LDAPProvider] MediaWiki\Extension\LDAPProvider\Client::getUserDN: search with array (
  'base' => 'DC=corp,DC=example,DC=com',
  'filter' => '(samaccountname=duckofdeath)',
  'attributes' =>
  array (
    0 => '*',
    1 => 'memberof',
  ),
)
[LDAPProvider] Found user DN: 'CN=Duck of Death,OU=Employees,DC=corp,DC=example,DC=com'
[LDAPProvider] MediaWiki\Extension\LDAPProvider\Client::getSearchString: User DN is: 'CN=Duck of Death,OU=Employees,DC=corp,DC=example,DC=com'
[DBConnection] Wikimedia\Rdbms\LoadBalancer::getLocalConnection: reused a connection for localAutoCommit/0
[DBQuery] SqlBagOStuff::fetchBlobs [0s] localhost: SELECT  keyname,value,exptime  FROM `objectcache`    WHERE keyname = 'cpcwiki:ldap-provider:user-info:duckofdeath:' AND (exptime >= '20220818222520')
[LDAPProvider] Ran LDAP search for '(samaccountname=duckofdeath)' in 0.0011868476867676 seconds.

[DBConnection] Wikimedia\Rdbms\LoadBalancer::getLocalConnection: reused a connection for localAutoCommit/0
[DBQuery] Wikimedia\Rdbms\DatabaseMysqlBase::getServerId [0s] localhost: SELECT @@server_id AS id
[DBQuery] SqlBagOStuff::modifyTableSpecificBlobsForSet [0.002s] localhost: REPLACE INTO `objectcache` (keyname,value,exptime) VALUES ('cpcwiki:ldap-provider:user-info:duckofdeath:','K´2°ª®^E\0','20220818223340')
[DBConnection] Wikimedia\Rdbms\LoadBalancer::getLocalConnection: reused a connection for localAutoCommit/0
**[error] [8a143c32a65ae413d7069df0] /index.php?title=Special:PluggableAuthLogin   PHP Notice: Undefined index: samaccountname**
#0 /var/www/mediawiki-1.38.2/extensions/LDAPAuthentication2/src/PluggableAuth.php(196): MWExceptionHandler::handleError()
#1 /var/www/mediawiki-1.38.2/extensions/LDAPAuthentication2/src/PluggableAuth.php(55): MediaWiki\Extension\LDAPAuthentication2\PluggableAuth->checkLDAPLogin()
#2 /var/www/mediawiki-1.38.2/extensions/PluggableAuth/includes/PluggableAuthLogin.php(36): MediaWiki\Extension\LDAPAuthentication2\PluggableAuth->authenticate()
#3 /var/www/mediawiki-1.38.2/includes/specialpage/SpecialPage.php(671): PluggableAuthLogin->execute()
#4 /var/www/mediawiki-1.38.2/includes/specialpage/SpecialPageFactory.php(1378): SpecialPage->run()
#5 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(315): MediaWiki\SpecialPage\SpecialPageFactory->executePath()
#6 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(912): MediaWiki->performRequest()
#7 /var/www/mediawiki-1.38.2/includes/MediaWiki.php(563): MediaWiki->main()
#8 /var/www/mediawiki-1.38.2/index.php(53): MediaWiki->run()
#9 /var/www/mediawiki-1.38.2/index.php(46): wfIndexMain()
#10 {main}
**[error] [8a143c32a65ae413d7069df0] /index.php?title=Special:PluggableAuthLogin   PHP Notice: Undefined index: cn**

I've run update.php twice now but I'm going to give the --force option a try, not sure if it would make a difference ... I guess I could read the code for checkLDAPLogin() and see what's going on..