3 namespace MediaWiki\Auth
;
5 use Wikimedia\TestingAccessWrapper
;
10 * @covers MediaWiki\Auth\ThrottlePreAuthenticationProvider
12 class ThrottlePreAuthenticationProviderTest
extends \MediaWikiTestCase
{
13 public function testConstructor() {
14 $provider = new ThrottlePreAuthenticationProvider();
15 $providerPriv = TestingAccessWrapper
::newFromObject( $provider );
16 $config = new \
HashConfig( [
17 'AccountCreationThrottle' => [ [
21 'PasswordAttemptThrottle' => [ [
26 $provider->setConfig( $config );
28 'accountCreationThrottle' => [ [ 'count' => 123, 'seconds' => 86400 ] ],
29 'passwordAttemptThrottle' => [ [ 'count' => 5, 'seconds' => 300 ] ]
30 ], $providerPriv->throttleSettings
);
31 $accountCreationThrottle = TestingAccessWrapper
::newFromObject(
32 $providerPriv->accountCreationThrottle
);
33 $this->assertSame( [ [ 'count' => 123, 'seconds' => 86400 ] ],
34 $accountCreationThrottle->conditions
);
35 $passwordAttemptThrottle = TestingAccessWrapper
::newFromObject(
36 $providerPriv->passwordAttemptThrottle
);
37 $this->assertSame( [ [ 'count' => 5, 'seconds' => 300 ] ],
38 $passwordAttemptThrottle->conditions
);
40 $provider = new ThrottlePreAuthenticationProvider( [
41 'accountCreationThrottle' => [ [ 'count' => 43, 'seconds' => 10000 ] ],
42 'passwordAttemptThrottle' => [ [ 'count' => 11, 'seconds' => 100 ] ],
44 $providerPriv = TestingAccessWrapper
::newFromObject( $provider );
45 $config = new \
HashConfig( [
46 'AccountCreationThrottle' => [ [
50 'PasswordAttemptThrottle' => [ [
55 $provider->setConfig( $config );
57 'accountCreationThrottle' => [ [ 'count' => 43, 'seconds' => 10000 ] ],
58 'passwordAttemptThrottle' => [ [ 'count' => 11, 'seconds' => 100 ] ],
59 ], $providerPriv->throttleSettings
);
61 $cache = new \
HashBagOStuff();
62 $provider = new ThrottlePreAuthenticationProvider( [ 'cache' => $cache ] );
63 $providerPriv = TestingAccessWrapper
::newFromObject( $provider );
64 $provider->setConfig( new \
HashConfig( [
65 'AccountCreationThrottle' => [ [ 'count' => 1, 'seconds' => 1 ] ],
66 'PasswordAttemptThrottle' => [ [ 'count' => 1, 'seconds' => 1 ] ],
68 $accountCreationThrottle = TestingAccessWrapper
::newFromObject(
69 $providerPriv->accountCreationThrottle
);
70 $this->assertSame( $cache, $accountCreationThrottle->cache
);
71 $passwordAttemptThrottle = TestingAccessWrapper
::newFromObject(
72 $providerPriv->passwordAttemptThrottle
);
73 $this->assertSame( $cache, $passwordAttemptThrottle->cache
);
76 public function testDisabled() {
77 $provider = new ThrottlePreAuthenticationProvider( [
78 'accountCreationThrottle' => [],
79 'passwordAttemptThrottle' => [],
80 'cache' => new \
HashBagOStuff(),
82 $provider->setLogger( new \Psr\Log\
NullLogger() );
83 $provider->setConfig( new \
HashConfig( [
84 'AccountCreationThrottle' => null,
85 'PasswordAttemptThrottle' => null,
87 $provider->setManager( AuthManager
::singleton() );
90 \StatusValue
::newGood(),
91 $provider->testForAccountCreation(
92 \User
::newFromName( 'Created' ),
93 \User
::newFromName( 'Creator' ),
98 \StatusValue
::newGood(),
99 $provider->testForAuthentication( [] )
104 * @dataProvider provideTestForAccountCreation
105 * @param string $creatorname
106 * @param bool $succeed
109 public function testTestForAccountCreation( $creatorname, $succeed, $hook ) {
110 $provider = new ThrottlePreAuthenticationProvider( [
111 'accountCreationThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
112 'cache' => new \
HashBagOStuff(),
114 $provider->setLogger( new \Psr\Log\
NullLogger() );
115 $provider->setConfig( new \
HashConfig( [
116 'AccountCreationThrottle' => null,
117 'PasswordAttemptThrottle' => null,
119 $provider->setManager( AuthManager
::singleton() );
121 $user = \User
::newFromName( 'RandomUser' );
122 $creator = \User
::newFromName( $creatorname );
124 $mock = $this->getMockBuilder( 'stdClass' )
125 ->setMethods( [ 'onExemptFromAccountCreationThrottle' ] )
127 $mock->expects( $this->any() )->method( 'onExemptFromAccountCreationThrottle' )
128 ->will( $this->returnValue( false ) );
129 $this->mergeMwGlobalArrayValue( 'wgHooks', [
130 'ExemptFromAccountCreationThrottle' => [ $mock ],
136 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
141 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
145 $succeed ?
true : false,
146 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
151 public static function provideTestForAccountCreation() {
153 'Normal user' => [ 'NormalUser', false, false ],
154 'Sysop' => [ 'UTSysop', true, false ],
155 'Normal user with hook' => [ 'NormalUser', true, true ],
159 public function testTestForAuthentication() {
160 $provider = new ThrottlePreAuthenticationProvider( [
161 'passwordAttemptThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
162 'cache' => new \
HashBagOStuff(),
164 $provider->setLogger( new \Psr\Log\
NullLogger() );
165 $provider->setConfig( new \
HashConfig( [
166 'AccountCreationThrottle' => null,
167 'PasswordAttemptThrottle' => null,
169 $provider->setManager( AuthManager
::singleton() );
171 $req = new UsernameAuthenticationRequest
;
172 $req->username
= 'SomeUser';
173 for ( $i = 1; $i <= 3; $i++
) {
174 $status = $provider->testForAuthentication( [ $req ] );
175 $this->assertEquals( $i < 3, $status->isGood(), "attempt #$i" );
177 $this->assertCount( 1, $status->getErrors() );
178 $msg = new \
Message( $status->getErrors()[0]['message'], $status->getErrors()[0]['params'] );
179 $this->assertEquals( 'login-throttled', $msg->getKey() );
181 $provider->postAuthentication( \User
::newFromName( 'SomeUser' ),
182 AuthenticationResponse
::newFail( wfMessage( 'foo' ) ) );
183 $this->assertFalse( $provider->testForAuthentication( [ $req ] )->isGood(), 'after FAIL' );
185 $provider->postAuthentication( \User
::newFromName( 'SomeUser' ),
186 AuthenticationResponse
::newPass() );
187 $this->assertTrue( $provider->testForAuthentication( [ $req ] )->isGood(), 'after PASS' );
189 $req1 = new UsernameAuthenticationRequest
;
190 $req1->username
= 'foo';
191 $req2 = new UsernameAuthenticationRequest
;
192 $req2->username
= 'bar';
193 $this->assertTrue( $provider->testForAuthentication( [ $req1, $req2 ] )->isGood() );
195 $req = new UsernameAuthenticationRequest
;
196 $req->username
= 'Some user';
197 $provider->testForAuthentication( [ $req ] );
198 $req->username
= 'Some_user';
199 $provider->testForAuthentication( [ $req ] );
200 $req->username
= 'some user';
201 $status = $provider->testForAuthentication( [ $req ] );
202 $this->assertFalse( $status->isGood(), 'denormalized usernames are normalized' );
205 public function testPostAuthentication() {
206 $provider = new ThrottlePreAuthenticationProvider( [
207 'passwordAttemptThrottle' => [],
208 'cache' => new \
HashBagOStuff(),
210 $provider->setLogger( new \TestLogger
);
211 $provider->setConfig( new \
HashConfig( [
212 'AccountCreationThrottle' => null,
213 'PasswordAttemptThrottle' => null,
215 $provider->setManager( AuthManager
::singleton() );
216 $provider->postAuthentication( \User
::newFromName( 'SomeUser' ),
217 AuthenticationResponse
::newPass() );
219 $provider = new ThrottlePreAuthenticationProvider( [
220 'passwordAttemptThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
221 'cache' => new \
HashBagOStuff(),
223 $logger = new \
TestLogger( true );
224 $provider->setLogger( $logger );
225 $provider->setConfig( new \
HashConfig( [
226 'AccountCreationThrottle' => null,
227 'PasswordAttemptThrottle' => null,
229 $provider->setManager( AuthManager
::singleton() );
230 $provider->postAuthentication( \User
::newFromName( 'SomeUser' ),
231 AuthenticationResponse
::newPass() );
233 [ \Psr\Log\LogLevel
::INFO
, 'throttler data not found for {user}' ],
234 ], $logger->getBuffer() );