Merge "Fix sessionfailure i18n message during authentication"
[lhc/web/wiklou.git] / tests / phpunit / includes / auth / ThrottlePreAuthenticationProviderTest.php
1 <?php
2
3 namespace MediaWiki\Auth;
4
5 use Wikimedia\TestingAccessWrapper;
6
7 /**
8 * @group AuthManager
9 * @group Database
10 * @covers MediaWiki\Auth\ThrottlePreAuthenticationProvider
11 */
12 class ThrottlePreAuthenticationProviderTest extends \MediaWikiTestCase {
13 public function testConstructor() {
14 $provider = new ThrottlePreAuthenticationProvider();
15 $providerPriv = TestingAccessWrapper::newFromObject( $provider );
16 $config = new \HashConfig( [
17 'AccountCreationThrottle' => [ [
18 'count' => 123,
19 'seconds' => 86400,
20 ] ],
21 'PasswordAttemptThrottle' => [ [
22 'count' => 5,
23 'seconds' => 300,
24 ] ],
25 ] );
26 $provider->setConfig( $config );
27 $this->assertSame( [
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 );
39
40 $provider = new ThrottlePreAuthenticationProvider( [
41 'accountCreationThrottle' => [ [ 'count' => 43, 'seconds' => 10000 ] ],
42 'passwordAttemptThrottle' => [ [ 'count' => 11, 'seconds' => 100 ] ],
43 ] );
44 $providerPriv = TestingAccessWrapper::newFromObject( $provider );
45 $config = new \HashConfig( [
46 'AccountCreationThrottle' => [ [
47 'count' => 123,
48 'seconds' => 86400,
49 ] ],
50 'PasswordAttemptThrottle' => [ [
51 'count' => 5,
52 'seconds' => 300,
53 ] ],
54 ] );
55 $provider->setConfig( $config );
56 $this->assertSame( [
57 'accountCreationThrottle' => [ [ 'count' => 43, 'seconds' => 10000 ] ],
58 'passwordAttemptThrottle' => [ [ 'count' => 11, 'seconds' => 100 ] ],
59 ], $providerPriv->throttleSettings );
60
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 ] ],
67 ] ) );
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 );
74 }
75
76 public function testDisabled() {
77 $provider = new ThrottlePreAuthenticationProvider( [
78 'accountCreationThrottle' => [],
79 'passwordAttemptThrottle' => [],
80 'cache' => new \HashBagOStuff(),
81 ] );
82 $provider->setLogger( new \Psr\Log\NullLogger() );
83 $provider->setConfig( new \HashConfig( [
84 'AccountCreationThrottle' => null,
85 'PasswordAttemptThrottle' => null,
86 ] ) );
87 $provider->setManager( AuthManager::singleton() );
88
89 $this->assertEquals(
90 \StatusValue::newGood(),
91 $provider->testForAccountCreation(
92 \User::newFromName( 'Created' ),
93 \User::newFromName( 'Creator' ),
94 []
95 )
96 );
97 $this->assertEquals(
98 \StatusValue::newGood(),
99 $provider->testForAuthentication( [] )
100 );
101 }
102
103 /**
104 * @dataProvider provideTestForAccountCreation
105 * @param string $creatorname
106 * @param bool $succeed
107 * @param bool $hook
108 */
109 public function testTestForAccountCreation( $creatorname, $succeed, $hook ) {
110 $provider = new ThrottlePreAuthenticationProvider( [
111 'accountCreationThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
112 'cache' => new \HashBagOStuff(),
113 ] );
114 $provider->setLogger( new \Psr\Log\NullLogger() );
115 $provider->setConfig( new \HashConfig( [
116 'AccountCreationThrottle' => null,
117 'PasswordAttemptThrottle' => null,
118 ] ) );
119 $provider->setManager( AuthManager::singleton() );
120
121 $user = \User::newFromName( 'RandomUser' );
122 $creator = \User::newFromName( $creatorname );
123 if ( $hook ) {
124 $mock = $this->getMockBuilder( stdClass::class )
125 ->setMethods( [ 'onExemptFromAccountCreationThrottle' ] )
126 ->getMock();
127 $mock->expects( $this->any() )->method( 'onExemptFromAccountCreationThrottle' )
128 ->will( $this->returnValue( false ) );
129 $this->mergeMwGlobalArrayValue( 'wgHooks', [
130 'ExemptFromAccountCreationThrottle' => [ $mock ],
131 ] );
132 }
133
134 $this->assertEquals(
135 true,
136 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
137 'attempt #1'
138 );
139 $this->assertEquals(
140 true,
141 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
142 'attempt #2'
143 );
144 $this->assertEquals(
145 $succeed ? true : false,
146 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
147 'attempt #3'
148 );
149 }
150
151 public static function provideTestForAccountCreation() {
152 return [
153 'Normal user' => [ 'NormalUser', false, false ],
154 'Sysop' => [ 'UTSysop', true, false ],
155 'Normal user with hook' => [ 'NormalUser', true, true ],
156 ];
157 }
158
159 public function testTestForAuthentication() {
160 $provider = new ThrottlePreAuthenticationProvider( [
161 'passwordAttemptThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
162 'cache' => new \HashBagOStuff(),
163 ] );
164 $provider->setLogger( new \Psr\Log\NullLogger() );
165 $provider->setConfig( new \HashConfig( [
166 'AccountCreationThrottle' => null,
167 'PasswordAttemptThrottle' => null,
168 ] ) );
169 $provider->setManager( AuthManager::singleton() );
170
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" );
176 }
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() );
180
181 $provider->postAuthentication( \User::newFromName( 'SomeUser' ),
182 AuthenticationResponse::newFail( wfMessage( 'foo' ) ) );
183 $this->assertFalse( $provider->testForAuthentication( [ $req ] )->isGood(), 'after FAIL' );
184
185 $provider->postAuthentication( \User::newFromName( 'SomeUser' ),
186 AuthenticationResponse::newPass() );
187 $this->assertTrue( $provider->testForAuthentication( [ $req ] )->isGood(), 'after PASS' );
188
189 $req1 = new UsernameAuthenticationRequest;
190 $req1->username = 'foo';
191 $req2 = new UsernameAuthenticationRequest;
192 $req2->username = 'bar';
193 $this->assertTrue( $provider->testForAuthentication( [ $req1, $req2 ] )->isGood() );
194
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' );
203 }
204
205 public function testPostAuthentication() {
206 $provider = new ThrottlePreAuthenticationProvider( [
207 'passwordAttemptThrottle' => [],
208 'cache' => new \HashBagOStuff(),
209 ] );
210 $provider->setLogger( new \TestLogger );
211 $provider->setConfig( new \HashConfig( [
212 'AccountCreationThrottle' => null,
213 'PasswordAttemptThrottle' => null,
214 ] ) );
215 $provider->setManager( AuthManager::singleton() );
216 $provider->postAuthentication( \User::newFromName( 'SomeUser' ),
217 AuthenticationResponse::newPass() );
218
219 $provider = new ThrottlePreAuthenticationProvider( [
220 'passwordAttemptThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
221 'cache' => new \HashBagOStuff(),
222 ] );
223 $logger = new \TestLogger( true );
224 $provider->setLogger( $logger );
225 $provider->setConfig( new \HashConfig( [
226 'AccountCreationThrottle' => null,
227 'PasswordAttemptThrottle' => null,
228 ] ) );
229 $provider->setManager( AuthManager::singleton() );
230 $provider->postAuthentication( \User::newFromName( 'SomeUser' ),
231 AuthenticationResponse::newPass() );
232 $this->assertSame( [
233 [ \Psr\Log\LogLevel::INFO, 'throttler data not found for {user}' ],
234 ], $logger->getBuffer() );
235 }
236 }