auth: Add AuthManagerFilterProviders hook
Allow disabling authentication providers. This allows for extensions to replace core providers with their own. This is using the $wgAuthManagerAutoConfig keys instead of AuthenticationProvider::getUniqueId() as the keys to filter. This makes it more useful for site administrators, and also it's probably the better known of the two identifiers so more intuitive. No effort is made to prevent the hook from filtering differently in different steps of the same authentication process. Bug: T369180 Change-Id: If5435b54a4fc08f685c04fc10eb44c6d72cd78fa
This commit is contained in:
parent
e04879ad01
commit
cde00b5585
6 changed files with 197 additions and 34 deletions
|
|
@ -113,7 +113,7 @@ For notes on 1.42.x and older releases, see HISTORY.
|
|||
accurate text representation of duration.
|
||||
* Added an interactive mode to the install.php maintenance script.
|
||||
* The ResourceLoaderModifyStartupSourceUrls hook was added.
|
||||
*
|
||||
* The AuthManagerFilterProviders hook was added.
|
||||
* …
|
||||
|
||||
=== External library changes in 1.43 ===
|
||||
|
|
|
|||
|
|
@ -869,6 +869,7 @@ $wgAutoloadLocalClasses = [
|
|||
'MediaWiki\\Auth\\CreatedAccountAuthenticationRequest' => __DIR__ . '/includes/auth/CreatedAccountAuthenticationRequest.php',
|
||||
'MediaWiki\\Auth\\CreationReasonAuthenticationRequest' => __DIR__ . '/includes/auth/CreationReasonAuthenticationRequest.php',
|
||||
'MediaWiki\\Auth\\EmailNotificationSecondaryAuthenticationProvider' => __DIR__ . '/includes/auth/EmailNotificationSecondaryAuthenticationProvider.php',
|
||||
'MediaWiki\\Auth\\Hook\\AuthManagerFilterProvidersHook' => __DIR__ . '/includes/auth/Hook/AuthManagerFilterProvidersHook.php',
|
||||
'MediaWiki\\Auth\\Hook\\AuthManagerLoginAuthenticateAuditHook' => __DIR__ . '/includes/auth/Hook/AuthManagerLoginAuthenticateAuditHook.php',
|
||||
'MediaWiki\\Auth\\Hook\\AuthPreserveQueryParamsHook' => __DIR__ . '/includes/auth/Hook/AuthPreserveQueryParamsHook.php',
|
||||
'MediaWiki\\Auth\\Hook\\ExemptFromAccountCreationThrottleHook' => __DIR__ . '/includes/auth/Hook/ExemptFromAccountCreationThrottleHook.php',
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ use Wikimedia\Rdbms\SelectQueryBuilder;
|
|||
*/
|
||||
class HookRunner implements
|
||||
\MediaWiki\Actions\Hook\GetActionNameHook,
|
||||
\MediaWiki\Auth\Hook\AuthManagerFilterProvidersHook,
|
||||
\MediaWiki\Auth\Hook\AuthManagerLoginAuthenticateAuditHook,
|
||||
\MediaWiki\Auth\Hook\AuthPreserveQueryParamsHook,
|
||||
\MediaWiki\Auth\Hook\ExemptFromAccountCreationThrottleHook,
|
||||
|
|
@ -886,6 +887,14 @@ class HookRunner implements
|
|||
);
|
||||
}
|
||||
|
||||
public function onAuthManagerFilterProviders( array &$providers ): void {
|
||||
$this->container->run(
|
||||
'AuthManagerFilterProviders',
|
||||
[ &$providers ],
|
||||
[ 'abortable' => false ]
|
||||
);
|
||||
}
|
||||
|
||||
public function onAuthManagerLoginAuthenticateAudit( $response, $user,
|
||||
$username, $extraData
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ namespace MediaWiki\Auth;
|
|||
|
||||
use IDBAccessObject;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use MediaWiki\Block\BlockManager;
|
||||
use MediaWiki\Config\Config;
|
||||
use MediaWiki\Context\RequestContext;
|
||||
|
|
@ -53,10 +54,12 @@ use MediaWiki\User\UserIdentityLookup;
|
|||
use MediaWiki\User\UserNameUtils;
|
||||
use MediaWiki\User\UserRigorOptions;
|
||||
use MediaWiki\Watchlist\WatchlistManager;
|
||||
use MWExceptionHandler;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use StatusValue;
|
||||
use Wikimedia\NormalizedException\NormalizedException;
|
||||
use Wikimedia\ObjectFactory\ObjectFactory;
|
||||
use Wikimedia\Rdbms\ILoadBalancer;
|
||||
use Wikimedia\Rdbms\ReadOnlyMode;
|
||||
|
|
@ -400,7 +403,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
if ( !$session->canSetUser() ) {
|
||||
// Caller should have called canAuthenticateNow()
|
||||
$session->remove( self::AUTHN_STATE );
|
||||
throw new \LogicException( 'Authentication is not possible now' );
|
||||
throw new LogicException( 'Authentication is not possible now' );
|
||||
}
|
||||
|
||||
$guessUserName = null;
|
||||
|
|
@ -424,7 +427,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
);
|
||||
if ( $req ) {
|
||||
if ( !in_array( $req, $this->createdAccountAuthenticationRequests, true ) ) {
|
||||
throw new \LogicException(
|
||||
throw new LogicException(
|
||||
'CreatedAccountAuthenticationRequests are only valid on ' .
|
||||
'the same AuthManager that created the account'
|
||||
);
|
||||
|
|
@ -481,6 +484,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
'reqs' => $reqs,
|
||||
'returnToUrl' => $returnToUrl,
|
||||
'guessUserName' => $guessUserName,
|
||||
'providerIds' => $this->getProviderIds(),
|
||||
'primary' => null,
|
||||
'primaryResponse' => null,
|
||||
'secondary' => [],
|
||||
|
|
@ -531,7 +535,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
if ( !$session->canSetUser() ) {
|
||||
// Caller should have called canAuthenticateNow()
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \LogicException( 'Authentication is not possible now' );
|
||||
throw new LogicException( 'Authentication is not possible now' );
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
|
|
@ -541,6 +545,26 @@ class AuthManager implements LoggerAwareInterface {
|
|||
wfMessage( 'authmanager-authn-not-in-progress' )
|
||||
);
|
||||
}
|
||||
if ( $state['providerIds'] !== $this->getProviderIds() ) {
|
||||
// An inconsistent AuthManagerFilterProviders hook, or site configuration changed
|
||||
// while the user was in the middle of authentication. The first is a bug, the
|
||||
// second is rare but expected when deploying a config change. Try handle in a way
|
||||
// that's useful for both cases.
|
||||
// @codeCoverageIgnoreStart
|
||||
MWExceptionHandler::logException( new NormalizedException(
|
||||
'Authentication failed because of inconsistent provider array',
|
||||
[ 'old' => json_encode( $state['providerIds'] ), 'new' => json_encode( $this->getProviderIds() ) ]
|
||||
) );
|
||||
$ret = AuthenticationResponse::newFail(
|
||||
wfMessage( 'authmanager-authn-not-in-progress' )
|
||||
);
|
||||
$this->callMethodOnProviders( 7, 'postAuthentication',
|
||||
[ $this->userFactory->newFromName( (string)$state['guessUserName'] ), $ret ]
|
||||
);
|
||||
$session->remove( self::AUTHN_STATE );
|
||||
return $ret;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
$state['continueRequests'] = [];
|
||||
|
||||
$guessUserName = $state['guessUserName'];
|
||||
|
|
@ -1272,7 +1296,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
if ( !$this->canCreateAccounts() ) {
|
||||
// Caller should have called canCreateAccounts()
|
||||
$session->remove( self::ACCOUNT_CREATION_STATE );
|
||||
throw new \LogicException( 'Account creation is not possible' );
|
||||
throw new LogicException( 'Account creation is not possible' );
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -1337,6 +1361,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
'creatorname' => $creator->getUser()->getName(),
|
||||
'reqs' => $reqs,
|
||||
'returnToUrl' => $returnToUrl,
|
||||
'providerIds' => $this->getProviderIds(),
|
||||
'primary' => null,
|
||||
'primaryResponse' => null,
|
||||
'secondary' => [],
|
||||
|
|
@ -1375,7 +1400,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
if ( !$this->canCreateAccounts() ) {
|
||||
// Caller should have called canCreateAccounts()
|
||||
$session->remove( self::ACCOUNT_CREATION_STATE );
|
||||
throw new \LogicException( 'Account creation is not possible' );
|
||||
throw new LogicException( 'Account creation is not possible' );
|
||||
}
|
||||
|
||||
$state = $session->getSecret( self::ACCOUNT_CREATION_STATE );
|
||||
|
|
@ -1407,6 +1432,25 @@ class AuthManager implements LoggerAwareInterface {
|
|||
$creator->setName( $state['creatorname'] );
|
||||
}
|
||||
|
||||
if ( $state['providerIds'] !== $this->getProviderIds() ) {
|
||||
// An inconsistent AuthManagerFilterProviders hook, or site configuration changed
|
||||
// while the user was in the middle of authentication. The first is a bug, the
|
||||
// second is rare but expected when deploying a config change. Try handle in a way
|
||||
// that's useful for both cases.
|
||||
// @codeCoverageIgnoreStart
|
||||
MWExceptionHandler::logException( new NormalizedException(
|
||||
'Authentication failed because of inconsistent provider array',
|
||||
[ 'old' => json_encode( $state['providerIds'] ), 'new' => json_encode( $this->getProviderIds() ) ]
|
||||
) );
|
||||
$ret = AuthenticationResponse::newFail(
|
||||
wfMessage( 'authmanager-create-not-in-progress' )
|
||||
);
|
||||
$this->callMethodOnProviders( 7, 'postAccountCreation', [ $user, $creator, $ret ] );
|
||||
$session->remove( self::ACCOUNT_CREATION_STATE );
|
||||
return $ret;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// Avoid account creation races on double submissions
|
||||
$cache = MediaWikiServices::getInstance()->getObjectCacheFactory()->getLocalClusterInstance();
|
||||
$lock = $cache->getScopedLock( $cache->makeGlobalKey( 'account', md5( $user->getName() ) ) );
|
||||
|
|
@ -2087,7 +2131,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
|
||||
if ( !$this->canLinkAccounts() ) {
|
||||
// Caller should have called canLinkAccounts()
|
||||
throw new \LogicException( 'Account linking is not possible' );
|
||||
throw new LogicException( 'Account linking is not possible' );
|
||||
}
|
||||
|
||||
if ( !$user->isRegistered() ) {
|
||||
|
|
@ -2124,6 +2168,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
'username' => $user->getName(),
|
||||
'userid' => $user->getId(),
|
||||
'returnToUrl' => $returnToUrl,
|
||||
'providerIds' => $this->getProviderIds(),
|
||||
'primary' => null,
|
||||
'continueRequests' => [],
|
||||
];
|
||||
|
|
@ -2196,7 +2241,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
if ( !$this->canLinkAccounts() ) {
|
||||
// Caller should have called canLinkAccounts()
|
||||
$session->remove( self::ACCOUNT_LINK_STATE );
|
||||
throw new \LogicException( 'Account linking is not possible' );
|
||||
throw new LogicException( 'Account linking is not possible' );
|
||||
}
|
||||
|
||||
$state = $session->getSecret( self::ACCOUNT_LINK_STATE );
|
||||
|
|
@ -2224,6 +2269,25 @@ class AuthManager implements LoggerAwareInterface {
|
|||
);
|
||||
}
|
||||
|
||||
if ( $state['providerIds'] !== $this->getProviderIds() ) {
|
||||
// An inconsistent AuthManagerFilterProviders hook, or site configuration changed
|
||||
// while the user was in the middle of authentication. The first is a bug, the
|
||||
// second is rare but expected when deploying a config change. Try handle in a way
|
||||
// that's useful for both cases.
|
||||
// @codeCoverageIgnoreStart
|
||||
MWExceptionHandler::logException( new NormalizedException(
|
||||
'Authentication failed because of inconsistent provider array',
|
||||
[ 'old' => json_encode( $state['providerIds'] ), 'new' => json_encode( $this->getProviderIds() ) ]
|
||||
) );
|
||||
$ret = AuthenticationResponse::newFail(
|
||||
wfMessage( 'authmanager-link-not-in-progress' )
|
||||
);
|
||||
$this->callMethodOnProviders( 7, 'postAccountCreation', [ $user, $ret ] );
|
||||
$session->remove( self::ACCOUNT_LINK_STATE );
|
||||
return $ret;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
foreach ( $reqs as $req ) {
|
||||
$req->username = $state['username'];
|
||||
$req->returnToUrl = $state['returnToUrl'];
|
||||
|
|
@ -2611,24 +2675,13 @@ class AuthManager implements LoggerAwareInterface {
|
|||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getConfiguration() {
|
||||
return $this->config->get( MainConfigNames::AuthManagerConfig )
|
||||
?: $this->config->get( MainConfigNames::AuthManagerAutoConfig );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of PreAuthenticationProviders
|
||||
* @return PreAuthenticationProvider[]
|
||||
*/
|
||||
protected function getPreAuthenticationProviders() {
|
||||
if ( $this->preAuthenticationProviders === null ) {
|
||||
$conf = $this->getConfiguration();
|
||||
$this->preAuthenticationProviders = $this->providerArrayFromSpecs(
|
||||
PreAuthenticationProvider::class, $conf['preauth']
|
||||
);
|
||||
$this->initializeAuthenticationProviders();
|
||||
}
|
||||
return $this->preAuthenticationProviders;
|
||||
}
|
||||
|
|
@ -2639,10 +2692,7 @@ class AuthManager implements LoggerAwareInterface {
|
|||
*/
|
||||
protected function getPrimaryAuthenticationProviders() {
|
||||
if ( $this->primaryAuthenticationProviders === null ) {
|
||||
$conf = $this->getConfiguration();
|
||||
$this->primaryAuthenticationProviders = $this->providerArrayFromSpecs(
|
||||
PrimaryAuthenticationProvider::class, $conf['primaryauth']
|
||||
);
|
||||
$this->initializeAuthenticationProviders();
|
||||
}
|
||||
return $this->primaryAuthenticationProviders;
|
||||
}
|
||||
|
|
@ -2653,14 +2703,40 @@ class AuthManager implements LoggerAwareInterface {
|
|||
*/
|
||||
protected function getSecondaryAuthenticationProviders() {
|
||||
if ( $this->secondaryAuthenticationProviders === null ) {
|
||||
$conf = $this->getConfiguration();
|
||||
$this->secondaryAuthenticationProviders = $this->providerArrayFromSpecs(
|
||||
SecondaryAuthenticationProvider::class, $conf['secondaryauth']
|
||||
);
|
||||
$this->initializeAuthenticationProviders();
|
||||
}
|
||||
return $this->secondaryAuthenticationProviders;
|
||||
}
|
||||
|
||||
private function getProviderIds(): array {
|
||||
return [
|
||||
'preauth' => array_keys( $this->getPreAuthenticationProviders() ),
|
||||
'primaryauth' => array_keys( $this->getPrimaryAuthenticationProviders() ),
|
||||
'secondaryauth' => array_keys( $this->getSecondaryAuthenticationProviders() ),
|
||||
];
|
||||
}
|
||||
|
||||
private function initializeAuthenticationProviders() {
|
||||
$conf = $this->config->get( MainConfigNames::AuthManagerConfig )
|
||||
?: $this->config->get( MainConfigNames::AuthManagerAutoConfig );
|
||||
|
||||
$providers = array_map( fn ( $stepConf ) => array_fill_keys( array_keys( $stepConf ), true ), $conf );
|
||||
$this->getHookRunner()->onAuthManagerFilterProviders( $providers );
|
||||
foreach ( $conf as $step => $stepConf ) {
|
||||
$conf[$step] = array_intersect_key( $stepConf, array_filter( $providers[$step] ) );
|
||||
}
|
||||
|
||||
$this->preAuthenticationProviders = $this->providerArrayFromSpecs(
|
||||
PreAuthenticationProvider::class, $conf['preauth']
|
||||
);
|
||||
$this->primaryAuthenticationProviders = $this->providerArrayFromSpecs(
|
||||
PrimaryAuthenticationProvider::class, $conf['primaryauth']
|
||||
);
|
||||
$this->secondaryAuthenticationProviders = $this->providerArrayFromSpecs(
|
||||
SecondaryAuthenticationProvider::class, $conf['secondaryauth']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the user in
|
||||
* @param User $user
|
||||
|
|
|
|||
41
includes/auth/Hook/AuthManagerFilterProvidersHook.php
Normal file
41
includes/auth/Hook/AuthManagerFilterProvidersHook.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\Auth\Hook;
|
||||
|
||||
use MediaWiki\MainConfigSchema;
|
||||
|
||||
/**
|
||||
* This is a hook handler interface, see docs/Hooks.md.
|
||||
* Use the hook name "AuthManagerFilterProviders" to register handlers implementing this interface.
|
||||
*
|
||||
* @stable to implement
|
||||
* @ingroup Hooks
|
||||
*/
|
||||
interface AuthManagerFilterProvidersHook {
|
||||
|
||||
/**
|
||||
* Filter the list of authentication available providers. Providers removed from the
|
||||
* list will be disabled for the current request, and any authentication process started
|
||||
* from the current request.
|
||||
*
|
||||
* Hook handlers don't have to always return the same result for the given configuration
|
||||
* (can depend on the request, e.g. feature flags) but they do have to be consistent
|
||||
* within an authentication process that spans multiple requests.
|
||||
*
|
||||
* @since 1.43
|
||||
*
|
||||
* @param bool[][] &$providers An array with three sub-arrays: 'preauth', 'primaryauth',
|
||||
* 'secondaryauth'. Each field in the subarrays is a map of <provider key> => true.
|
||||
* (The provider key is the same array key that's used in $wgAuthManagerAutoConfig or
|
||||
* $wgAuthManagerConfig). Unsetting a field or setting its value to falsy disables the
|
||||
* corresponding provider.
|
||||
* @phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
* @phan-param array{preauth:array<string,true>,primaryauth:array<string,true>,secondaryauth:array<string,true>} $providers
|
||||
* @return void This hook must not abort, it must return no value
|
||||
*
|
||||
* @see https://www.mediawiki.org/wiki/Manual:Hooks/AuthManagerFilterProviders
|
||||
* @see MainConfigSchema::AuthManagerAutoConfig
|
||||
*/
|
||||
public function onAuthManagerFilterProviders( array &$providers ): void;
|
||||
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ class AuthManagerTest extends MediaWikiIntegrationTestCase {
|
|||
|
||||
/** @var AuthManager */
|
||||
protected $manager;
|
||||
/** @var TestingAccessWrapper */
|
||||
/** @var TestingAccessWrapper|AuthManager */
|
||||
protected $managerPriv;
|
||||
|
||||
/** @var BlockManager */
|
||||
|
|
@ -339,8 +339,7 @@ class AuthManagerTest extends MediaWikiIntegrationTestCase {
|
|||
$this->botPasswordStore,
|
||||
$this->userFactory,
|
||||
$this->userIdentityLookup,
|
||||
$this->userOptionsManager,
|
||||
$this->objectCacheFactory
|
||||
$this->userOptionsManager
|
||||
);
|
||||
$this->manager->setLogger( $this->logger );
|
||||
$this->managerPriv = TestingAccessWrapper::newFromObject( $this->manager );
|
||||
|
|
@ -713,7 +712,7 @@ class AuthManagerTest extends MediaWikiIntegrationTestCase {
|
|||
$class1 = get_class( $mock1 );
|
||||
$class2 = get_class( $mock2 );
|
||||
$this->assertSame(
|
||||
"Duplicate specifications for id X (classes $class1 and $class2)", $ex->getMessage()
|
||||
"Duplicate specifications for id X (classes $class2 and $class1)", $ex->getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -722,8 +721,8 @@ class AuthManagerTest extends MediaWikiIntegrationTestCase {
|
|||
$mock->method( 'getUniqueId' )->willReturn( 'X' );
|
||||
$class = get_class( $mock );
|
||||
$this->preauthMocks = [ $mock ];
|
||||
$this->primaryauthMocks = [ $mock ];
|
||||
$this->secondaryauthMocks = [ $mock ];
|
||||
$this->primaryauthMocks = [];
|
||||
$this->secondaryauthMocks = [];
|
||||
$this->initializeManager( true );
|
||||
try {
|
||||
$this->managerPriv->getPreAuthenticationProviders();
|
||||
|
|
@ -734,6 +733,10 @@ class AuthManagerTest extends MediaWikiIntegrationTestCase {
|
|||
$ex->getMessage()
|
||||
);
|
||||
}
|
||||
$this->preauthMocks = [];
|
||||
$this->primaryauthMocks = [ $mock ];
|
||||
$this->secondaryauthMocks = [];
|
||||
$this->initializeManager( true );
|
||||
try {
|
||||
$this->managerPriv->getPrimaryAuthenticationProviders();
|
||||
$this->fail( 'Expected exception not thrown' );
|
||||
|
|
@ -743,6 +746,10 @@ class AuthManagerTest extends MediaWikiIntegrationTestCase {
|
|||
$ex->getMessage()
|
||||
);
|
||||
}
|
||||
$this->preauthMocks = [];
|
||||
$this->primaryauthMocks = [];
|
||||
$this->secondaryauthMocks = [ $mock ];
|
||||
$this->initializeManager( true );
|
||||
try {
|
||||
$this->managerPriv->getSecondaryAuthenticationProviders();
|
||||
$this->fail( 'Expected exception not thrown' );
|
||||
|
|
@ -780,6 +787,33 @@ class AuthManagerTest extends MediaWikiIntegrationTestCase {
|
|||
[ 'C' => $mock3, 'B' => $mock2, 'A' => $mock1 ],
|
||||
$this->managerPriv->getPrimaryAuthenticationProviders()
|
||||
);
|
||||
|
||||
// filtering
|
||||
$mockPreAuth1 = $this->createMock( AbstractPreAuthenticationProvider::class );
|
||||
$mockPreAuth2 = $this->createMock( AbstractPreAuthenticationProvider::class );
|
||||
$mockPrimary1 = $this->createMock( AbstractPrimaryAuthenticationProvider::class );
|
||||
$mockPrimary2 = $this->createMock( AbstractPrimaryAuthenticationProvider::class );
|
||||
$mockSecondary1 = $this->createMock( AbstractSecondaryAuthenticationProvider::class );
|
||||
$mockSecondary2 = $this->createMock( AbstractSecondaryAuthenticationProvider::class );
|
||||
$mockPreAuth1->method( 'getUniqueId' )->willReturn( 'pre1' );
|
||||
$mockPreAuth2->method( 'getUniqueId' )->willReturn( 'pre2' );
|
||||
$mockPrimary1->method( 'getUniqueId' )->willReturn( 'primary1' );
|
||||
$mockPrimary2->method( 'getUniqueId' )->willReturn( 'primary2' );
|
||||
$mockSecondary1->method( 'getUniqueId' )->willReturn( 'secondary1' );
|
||||
$mockSecondary2->method( 'getUniqueId' )->willReturn( 'secondary2' );
|
||||
$this->preauthMocks = [ $mockPreAuth1, $mockPreAuth2 ];
|
||||
$this->primaryauthMocks = [ $mockPrimary1, $mockPrimary2 ];
|
||||
$this->secondaryauthMocks = [ $mockSecondary1, $mockSecondary2 ];
|
||||
$this->initializeConfig();
|
||||
$this->initializeManager( true );
|
||||
$this->hookContainer->register( 'AuthManagerFilterProviders', static function ( &$providers ) {
|
||||
unset( $providers['preauth']['pre1'] );
|
||||
$providers['primaryauth']['primary2'] = false;
|
||||
$providers['secondaryauth'] = [ 'secondary2' => true ];
|
||||
} );
|
||||
$this->assertSame( [ 'pre2' => $mockPreAuth2 ], $this->managerPriv->getPreAuthenticationProviders() );
|
||||
$this->assertSame( [ 'primary1' => $mockPrimary1 ], $this->managerPriv->getPrimaryAuthenticationProviders() );
|
||||
$this->assertSame( [ 'secondary2' => $mockSecondary2 ], $this->managerPriv->getSecondaryAuthenticationProviders() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2013,6 +2047,7 @@ class AuthManagerTest extends MediaWikiIntegrationTestCase {
|
|||
'creatorid' => 0,
|
||||
'creatorname' => $username,
|
||||
'reqs' => [],
|
||||
'providerIds' => [ 'preauth' => [], 'primaryauth' => [], 'secondaryauth' => [] ],
|
||||
'primary' => null,
|
||||
'primaryResponse' => null,
|
||||
'secondary' => [],
|
||||
|
|
@ -2036,6 +2071,7 @@ class AuthManagerTest extends MediaWikiIntegrationTestCase {
|
|||
$mock->method( 'beginPrimaryAccountCreation' )
|
||||
->willReturn( AuthenticationResponse::newFail( $this->message( 'fail' ) ) );
|
||||
$this->primaryauthMocks = [ $mock ];
|
||||
$session['providerIds']['primaryauth'][] = 'X';
|
||||
$this->initializeManager( true );
|
||||
|
||||
$this->request->getSession()->setSecret( AuthManager::ACCOUNT_CREATION_STATE, null );
|
||||
|
|
|
|||
Loading…
Reference in a new issue