3 namespace MediaWiki\Auth
;
5 use Wikimedia\TestingAccessWrapper
;
11 * @covers \MediaWiki\Auth\ThrottlePreAuthenticationProvider
13 class ThrottlePreAuthenticationProviderTest
extends \MediaWikiTestCase
{
14 public function testConstructor() {
15 $provider = new ThrottlePreAuthenticationProvider();
16 $providerPriv = TestingAccessWrapper
::newFromObject( $provider );
17 $config = new \
HashConfig( [
18 'AccountCreationThrottle' => [ [
22 'PasswordAttemptThrottle' => [ [
27 $provider->setConfig( $config );
29 'accountCreationThrottle' => [ [ 'count' => 123, 'seconds' => 86400 ] ],
30 'passwordAttemptThrottle' => [ [ 'count' => 5, 'seconds' => 300 ] ]
31 ], $providerPriv->throttleSettings
);
32 $accountCreationThrottle = TestingAccessWrapper
::newFromObject(
33 $providerPriv->accountCreationThrottle
);
34 $this->assertSame( [ [ 'count' => 123, 'seconds' => 86400 ] ],
35 $accountCreationThrottle->conditions
);
36 $passwordAttemptThrottle = TestingAccessWrapper
::newFromObject(
37 $providerPriv->passwordAttemptThrottle
);
38 $this->assertSame( [ [ 'count' => 5, 'seconds' => 300 ] ],
39 $passwordAttemptThrottle->conditions
);
41 $provider = new ThrottlePreAuthenticationProvider( [
42 'accountCreationThrottle' => [ [ 'count' => 43, 'seconds' => 10000 ] ],
43 'passwordAttemptThrottle' => [ [ 'count' => 11, 'seconds' => 100 ] ],
45 $providerPriv = TestingAccessWrapper
::newFromObject( $provider );
46 $config = new \
HashConfig( [
47 'AccountCreationThrottle' => [ [
51 'PasswordAttemptThrottle' => [ [
56 $provider->setConfig( $config );
58 'accountCreationThrottle' => [ [ 'count' => 43, 'seconds' => 10000 ] ],
59 'passwordAttemptThrottle' => [ [ 'count' => 11, 'seconds' => 100 ] ],
60 ], $providerPriv->throttleSettings
);
62 $cache = new \
HashBagOStuff();
63 $provider = new ThrottlePreAuthenticationProvider( [ 'cache' => $cache ] );
64 $providerPriv = TestingAccessWrapper
::newFromObject( $provider );
65 $provider->setConfig( new \
HashConfig( [
66 'AccountCreationThrottle' => [ [ 'count' => 1, 'seconds' => 1 ] ],
67 'PasswordAttemptThrottle' => [ [ 'count' => 1, 'seconds' => 1 ] ],
69 $accountCreationThrottle = TestingAccessWrapper
::newFromObject(
70 $providerPriv->accountCreationThrottle
);
71 $this->assertSame( $cache, $accountCreationThrottle->cache
);
72 $passwordAttemptThrottle = TestingAccessWrapper
::newFromObject(
73 $providerPriv->passwordAttemptThrottle
);
74 $this->assertSame( $cache, $passwordAttemptThrottle->cache
);
77 public function testDisabled() {
78 $provider = new ThrottlePreAuthenticationProvider( [
79 'accountCreationThrottle' => [],
80 'passwordAttemptThrottle' => [],
81 'cache' => new \
HashBagOStuff(),
83 $provider->setLogger( new \Psr\Log\
NullLogger() );
84 $provider->setConfig( new \
HashConfig( [
85 'AccountCreationThrottle' => null,
86 'PasswordAttemptThrottle' => null,
88 $provider->setManager( AuthManager
::singleton() );
91 \StatusValue
::newGood(),
92 $provider->testForAccountCreation(
93 \User
::newFromName( 'Created' ),
94 \User
::newFromName( 'Creator' ),
99 \StatusValue
::newGood(),
100 $provider->testForAuthentication( [] )
105 * @dataProvider provideTestForAccountCreation
106 * @param string $creatorname
107 * @param bool $succeed
110 public function testTestForAccountCreation( $creatorname, $succeed, $hook ) {
111 $provider = new ThrottlePreAuthenticationProvider( [
112 'accountCreationThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
113 'cache' => new \
HashBagOStuff(),
115 $provider->setLogger( new \Psr\Log\
NullLogger() );
116 $provider->setConfig( new \
HashConfig( [
117 'AccountCreationThrottle' => null,
118 'PasswordAttemptThrottle' => null,
120 $provider->setManager( AuthManager
::singleton() );
122 $user = \User
::newFromName( 'RandomUser' );
123 $creator = \User
::newFromName( $creatorname );
125 $mock = $this->getMockBuilder( stdClass
::class )
126 ->setMethods( [ 'onExemptFromAccountCreationThrottle' ] )
128 $mock->expects( $this->any() )->method( 'onExemptFromAccountCreationThrottle' )
129 ->will( $this->returnValue( false ) );
130 $this->mergeMwGlobalArrayValue( 'wgHooks', [
131 'ExemptFromAccountCreationThrottle' => [ $mock ],
137 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
142 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
146 $succeed ?
true : false,
147 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
152 public static function provideTestForAccountCreation() {
154 'Normal user' => [ 'NormalUser', false, false ],
155 'Sysop' => [ 'UTSysop', true, false ],
156 'Normal user with hook' => [ 'NormalUser', true, true ],
160 public function testTestForAuthentication() {
161 $provider = new ThrottlePreAuthenticationProvider( [
162 'passwordAttemptThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
163 'cache' => new \
HashBagOStuff(),
165 $provider->setLogger( new \Psr\Log\
NullLogger() );
166 $provider->setConfig( new \
HashConfig( [
167 'AccountCreationThrottle' => null,
168 'PasswordAttemptThrottle' => null,
170 $provider->setManager( AuthManager
::singleton() );
172 $req = new UsernameAuthenticationRequest
;
173 $req->username
= 'SomeUser';
174 for ( $i = 1; $i <= 3; $i++
) {
175 $status = $provider->testForAuthentication( [ $req ] );
176 $this->assertEquals( $i < 3, $status->isGood(), "attempt #$i" );
178 $this->assertCount( 1, $status->getErrors() );
179 $msg = new \
Message( $status->getErrors()[0]['message'], $status->getErrors()[0]['params'] );
180 $this->assertEquals( 'login-throttled', $msg->getKey() );
182 $provider->postAuthentication( \User
::newFromName( 'SomeUser' ),
183 AuthenticationResponse
::newFail( wfMessage( 'foo' ) ) );
184 $this->assertFalse( $provider->testForAuthentication( [ $req ] )->isGood(), 'after FAIL' );
186 $provider->postAuthentication( \User
::newFromName( 'SomeUser' ),
187 AuthenticationResponse
::newPass() );
188 $this->assertTrue( $provider->testForAuthentication( [ $req ] )->isGood(), 'after PASS' );
190 $req1 = new UsernameAuthenticationRequest
;
191 $req1->username
= 'foo';
192 $req2 = new UsernameAuthenticationRequest
;
193 $req2->username
= 'bar';
194 $this->assertTrue( $provider->testForAuthentication( [ $req1, $req2 ] )->isGood() );
196 $req = new UsernameAuthenticationRequest
;
197 $req->username
= 'Some user';
198 $provider->testForAuthentication( [ $req ] );
199 $req->username
= 'Some_user';
200 $provider->testForAuthentication( [ $req ] );
201 $req->username
= 'some user';
202 $status = $provider->testForAuthentication( [ $req ] );
203 $this->assertFalse( $status->isGood(), 'denormalized usernames are normalized' );
206 public function testPostAuthentication() {
207 $provider = new ThrottlePreAuthenticationProvider( [
208 'passwordAttemptThrottle' => [],
209 'cache' => new \
HashBagOStuff(),
211 $provider->setLogger( new \TestLogger
);
212 $provider->setConfig( new \
HashConfig( [
213 'AccountCreationThrottle' => null,
214 'PasswordAttemptThrottle' => null,
216 $provider->setManager( AuthManager
::singleton() );
217 $provider->postAuthentication( \User
::newFromName( 'SomeUser' ),
218 AuthenticationResponse
::newPass() );
220 $provider = new ThrottlePreAuthenticationProvider( [
221 'passwordAttemptThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
222 'cache' => new \
HashBagOStuff(),
224 $logger = new \
TestLogger( true );
225 $provider->setLogger( $logger );
226 $provider->setConfig( new \
HashConfig( [
227 'AccountCreationThrottle' => null,
228 'PasswordAttemptThrottle' => null,
230 $provider->setManager( AuthManager
::singleton() );
231 $provider->postAuthentication( \User
::newFromName( 'SomeUser' ),
232 AuthenticationResponse
::newPass() );
234 [ \Psr\Log\LogLevel
::INFO
, 'throttler data not found for {user}' ],
235 ], $logger->getBuffer() );