Page MenuHomePhabricator

TypeError: Argument to UserNameUtils::getCanonical() must be string in AbstractPrimaryAuthenticationProvider.php (Unable to login)
Closed, ResolvedPublicPRODUCTION ERROR

Description

Error
normalized_message
[{reqId}] {exception_url}   TypeError: Argument 1 passed to MediaWiki\User\UserNameUtils::getCanonical() must be of the type string, null given, called in /srv/mediawiki/php-1.37.0-wmf.11/includes/auth/AbstractPrimaryAuthenticationProvider.php on line 70
exception.trace
from /srv/mediawiki/php-1.37.0-wmf.11/includes/user/UserNameUtils.php(258)
#0 /srv/mediawiki/php-1.37.0-wmf.11/includes/auth/AbstractPrimaryAuthenticationProvider.php(70): MediaWiki\User\UserNameUtils->getCanonical(NULL)
#1 /srv/mediawiki/php-1.37.0-wmf.11/includes/auth/AuthManager.php(863): MediaWiki\Auth\AbstractPrimaryAuthenticationProvider->providerNormalizeUsername(NULL)
#2 /srv/mediawiki/php-1.37.0-wmf.11/includes/auth/ThrottlePreAuthenticationProvider.php(134): MediaWiki\Auth\AuthManager->normalizeUsername(NULL)
#3 /srv/mediawiki/php-1.37.0-wmf.11/includes/auth/AuthManager.php(377): MediaWiki\Auth\ThrottlePreAuthenticationProvider->testForAuthentication(array)
#4 /srv/mediawiki/php-1.37.0-wmf.11/includes/api/ApiClientLogin.php(103): MediaWiki\Auth\AuthManager->beginAuthentication(array, string)
#5 /srv/mediawiki/php-1.37.0-wmf.11/includes/api/ApiMain.php(1721): ApiClientLogin->execute()
#6 /srv/mediawiki/php-1.37.0-wmf.11/includes/api/ApiMain.php(702): ApiMain->executeAction()
#7 /srv/mediawiki/php-1.37.0-wmf.11/includes/api/ApiMain.php(673): ApiMain->executeActionWithErrorHandling()
#8 /srv/mediawiki/php-1.37.0-wmf.11/api.php(90): ApiMain->execute()
#9 /srv/mediawiki/php-1.37.0-wmf.11/api.php(45): wfApiMain()
#10 /srv/mediawiki/w/api.php(3): require(string)
#11 {main}
Impact

Users are sometimes unable to login. Their login request receives a fatal error.

Notes

This was first spotted outside production on the Not Wikilambda wiki in Toolforge, where it caused logins to be broken.

Stack trace
/w/index.php?title=Special:UserLogin&returnto=Main+Page TypeError: Argument 1 passed to MediaWiki\User\UserNameUtils::getCanonical() must be of the type string, null given, called in /data/project/notwikilambda/public_html/w/includes/auth/AbstractPrimaryAuthenticationProvider.php on line 70

Backtrace:

from /data/project/notwikilambda/public_html/w/includes/user/UserNameUtils.php(258)
#0 /data/project/notwikilambda/public_html/w/includes/auth/AbstractPrimaryAuthenticationProvider.php(70): MediaWiki\User\UserNameUtils->getCanonical(NULL)
#1 /data/project/notwikilambda/public_html/w/includes/auth/AuthManager.php(877): MediaWiki\Auth\AbstractPrimaryAuthenticationProvider->providerNormalizeUsername(NULL)
#2 /data/project/notwikilambda/public_html/w/includes/auth/ThrottlePreAuthenticationProvider.php(134): MediaWiki\Auth\AuthManager->normalizeUsername(NULL)
#3 /data/project/notwikilambda/public_html/w/includes/auth/AuthManager.php(391): MediaWiki\Auth\ThrottlePreAuthenticationProvider->testForAuthentication(array)
#4 /data/project/notwikilambda/public_html/w/includes/specialpage/AuthManagerSpecialPage.php(372): MediaWiki\Auth\AuthManager->beginAuthentication(array, string)
#5 /data/project/notwikilambda/public_html/w/includes/specialpage/AuthManagerSpecialPage.php(502): AuthManagerSpecialPage->performAuthenticationStep(string, array)
#6 /data/project/notwikilambda/public_html/w/includes/htmlform/HTMLForm.php(718): AuthManagerSpecialPage->handleFormSubmit(array, VFormHTMLForm)
#7 /data/project/notwikilambda/public_html/w/includes/specialpage/AuthManagerSpecialPage.php(435): HTMLForm->trySubmit()
#8 /data/project/notwikilambda/public_html/w/includes/specialpage/LoginSignupSpecialPage.php(318): AuthManagerSpecialPage->trySubmit()
#9 /data/project/notwikilambda/public_html/w/includes/specialpage/SpecialPage.php(646): LoginSignupSpecialPage->execute(NULL)
#10 /data/project/notwikilambda/public_html/w/includes/specialpage/SpecialPageFactory.php(1362): SpecialPage->run(NULL)
#11 /data/project/notwikilambda/public_html/w/includes/MediaWiki.php(314): MediaWiki\SpecialPage\SpecialPageFactory->executePath(string, RequestContext)
#12 /data/project/notwikilambda/public_html/w/includes/MediaWiki.php(917): MediaWiki->performRequest()
#13 /data/project/notwikilambda/public_html/w/includes/MediaWiki.php(551): MediaWiki->main()
#14 /data/project/notwikilambda/public_html/w/index.php(53): MediaWiki->run()
#15 /data/project/notwikilambda/public_html/w/index.php(46): wfIndexMain()
#16 {main}

The wiki has PluggableAuth and WSOAuth installed (see also setup), but neither shows up in the stack trace, and it seems to me that the bug might be in core alone. Specifically:

  • #3 is in AuthManager::beginAuthentication(), calling $provider->testForAuthentication( $reqs );, where $provider is a PreAuthenticationProvider returned by getPreAuthenticationProviders() – specifically, apparently, a ThrottlePreAuthenticationProvider.
  • #2 is in ThrottlePreAuthenticationProvider::testForAuthentication(), calling $this->manager->normalizeUsername( $username ). $username came from AuthenticationRequest::getUsernameFromRequests( $reqs ) a few lines earlier, and AuthenticationRequest::getUsernameFromRequests() is documented to return string|null.
  • #1 is in AuthManager::normalizeUsername(), a method which is documented to take a string $username.

To me this looks like the bug is in ThrottlePreAuthenticationProvider: it gets a potentially-null $username and passes it directly into a method which requires a non-null string, without accounting for the possible null value.

However, Not Wikilambda logins only seem to have broken very recently (the recent changes show edits on 29 and 30 May, and sessions on this wiki are rather short-lived for unknown reasons, so I’m pretty sure logins worked on those days), and I haven’t been able to spot any code changes in these classes that might have caused this – they all haven’t had that many changes recently. So there’s something going on that I don’t understand yet.

Details

Request URL
https://en.wikipedia.org/w/api.php?format=*&formatversion=*&errorformat=*&action=clientlogin&rememberMe=*

Event Timeline

LucasWerkmeister renamed this task from Login broken on Not Wikilambda: null username ThrottlePreAuthenticationProvider and AuthManager to Login broken on Not Wikilambda: null username between ThrottlePreAuthenticationProvider and AuthManager.Jun 2 2021, 6:12 PM
LucasWerkmeister updated the task description. (Show Details)

Workaround, deconfiguring ThrottlePreAuthenticationProvider:

LocalSettings.php
if ( wfStringToBool( $_GET['notwikilambda-clear-preauth'] ?? 'true' ) ) {
        $wgAuthManagerAutoConfig['preauth'] = [];
}

You can still get the error by adding &notwikilambda-clear-preauth=false to the login URL (example).

Mentioned in SAL (#wikimedia-cloud) [2021-06-02T18:33:59Z] <wm-bot> <lucaswerkmeister> deployed workaround for broken login (T284170#7129989)

Change 697846 had a related patch set uploaded (by Lucas Werkmeister; author: Lucas Werkmeister):

[mediawiki/core@master] Handle null usernames in ThrottlePreAuthenticationProvider

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

Krinkle renamed this task from Login broken on Not Wikilambda: null username between ThrottlePreAuthenticationProvider and AuthManager to TypeError: Argument to UserNameUtils::getCanonical() must be string in AbstractPrimaryAuthenticationProvider.php (Unable to login).Jun 28 2021, 7:51 PM
Krinkle triaged this task as High priority.
Krinkle updated the task description. (Show Details)
Krinkle moved this task from Untriaged to June 2021 on the Wikimedia-production-error board.
Krinkle added a project: Platform Engineering.
Krinkle changed the subtype of this task from "Task" to "Production Error".
Krinkle set Request URL to https://en.wikipedia.org/w/api.php?format=*&formatversion=*&errorformat=*&action=clientlogin&rememberMe=*.

Change 697846 merged by jenkins-bot:

[mediawiki/core@master] Handle null usernames in ThrottlePreAuthenticationProvider

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

You can still get the error by adding &notwikilambda-clear-preauth=false to the login URL (example).

This no longer produces an error, so I guess the fix works. It sounds like we still don’t know why it happened? (Happened every time on Not Wikilambda since beginning of June, then sometimes started happening in prod but only later… strange)

BPirkle claimed this task.