]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - tests/security/LoginManagerTest.php
Merge branch 'v0.11' into stable
[github/shaarli/Shaarli.git] / tests / security / LoginManagerTest.php
CommitLineData
44acf706 1<?php
fab87c26 2namespace Shaarli\Security;
44acf706
V
3
4require_once 'tests/utils/FakeConfigManager.php';
dea72c71
V
5
6use PHPUnit\Framework\TestCase;
44acf706
V
7
8/**
9 * Test coverage for LoginManager
10 */
11class LoginManagerTest extends TestCase
12{
704637bf 13 /** @var \FakeConfigManager Configuration Manager instance */
44acf706 14 protected $configManager = null;
704637bf
V
15
16 /** @var LoginManager Login Manager instance */
44acf706 17 protected $loginManager = null;
704637bf
V
18
19 /** @var SessionManager Session Manager instance */
20 protected $sessionManager = null;
21
22 /** @var string Banned IP filename */
44acf706 23 protected $banFile = 'sandbox/ipbans.php';
704637bf
V
24
25 /** @var string Log filename */
44acf706 26 protected $logFile = 'sandbox/shaarli.log';
704637bf
V
27
28 /** @var array Simulates the $_COOKIE array */
29 protected $cookie = [];
30
31 /** @var array Simulates the $GLOBALS array */
44acf706 32 protected $globals = [];
704637bf
V
33
34 /** @var array Simulates the $_SERVER array */
44acf706 35 protected $server = [];
704637bf
V
36
37 /** @var array Simulates the $_SESSION array */
38 protected $session = [];
39
40 /** @var string Advertised client IP address */
41 protected $clientIpAddress = '10.1.47.179';
42
43 /** @var string Local client IP address */
44 protected $ipAddr = '127.0.0.1';
45
46 /** @var string Trusted proxy IP address */
44acf706
V
47 protected $trustedProxy = '10.1.1.100';
48
c689e108
V
49 /** @var string User login */
50 protected $login = 'johndoe';
51
52 /** @var string User password */
53 protected $password = 'IC4nHazL0g1n?';
54
55 /** @var string Hash of the salted user password */
56 protected $passwordHash = '';
57
58 /** @var string Salt used by hash functions */
59 protected $salt = '669e24fa9c5a59a613f98e8e38327384504a4af2';
60
44acf706
V
61 /**
62 * Prepare or reset test resources
63 */
64 public function setUp()
65 {
66 if (file_exists($this->banFile)) {
67 unlink($this->banFile);
68 }
69
c689e108
V
70 $this->passwordHash = sha1($this->password . $this->login . $this->salt);
71
44acf706 72 $this->configManager = new \FakeConfigManager([
c689e108
V
73 'credentials.login' => $this->login,
74 'credentials.hash' => $this->passwordHash,
75 'credentials.salt' => $this->salt,
44acf706
V
76 'resource.ban_file' => $this->banFile,
77 'resource.log' => $this->logFile,
b49a04f7 78 'security.ban_after' => 2,
44acf706
V
79 'security.ban_duration' => 3600,
80 'security.trusted_proxies' => [$this->trustedProxy],
81 ]);
82
704637bf 83 $this->cookie = [];
8edd7f15 84 $this->session = [];
704637bf
V
85
86 $this->sessionManager = new SessionManager($this->session, $this->configManager);
b49a04f7 87 $this->loginManager = new LoginManager($this->configManager, $this->sessionManager);
44acf706
V
88 $this->server['REMOTE_ADDR'] = $this->ipAddr;
89 }
90
44acf706
V
91 /**
92 * Record a failed login attempt
93 */
94 public function testHandleFailedLogin()
95 {
96 $this->loginManager->handleFailedLogin($this->server);
44acf706 97 $this->loginManager->handleFailedLogin($this->server);
b49a04f7 98 $this->assertFalse($this->loginManager->canLogin($this->server));
44acf706
V
99 }
100
101 /**
102 * Record a failed login attempt - IP behind a trusted proxy
103 */
104 public function testHandleFailedLoginBehindTrustedProxy()
105 {
106 $server = [
107 'REMOTE_ADDR' => $this->trustedProxy,
108 'HTTP_X_FORWARDED_FOR' => $this->ipAddr,
109 ];
110 $this->loginManager->handleFailedLogin($server);
44acf706 111 $this->loginManager->handleFailedLogin($server);
b49a04f7 112 $this->assertFalse($this->loginManager->canLogin($server));
44acf706
V
113 }
114
115 /**
116 * Record a failed login attempt - IP behind a trusted proxy but not forwarded
117 */
118 public function testHandleFailedLoginBehindTrustedProxyNoIp()
119 {
120 $server = [
121 'REMOTE_ADDR' => $this->trustedProxy,
122 ];
123 $this->loginManager->handleFailedLogin($server);
44acf706 124 $this->loginManager->handleFailedLogin($server);
b49a04f7 125 $this->assertTrue($this->loginManager->canLogin($server));
44acf706
V
126 }
127
128 /**
129 * Nothing to do
130 */
131 public function testHandleSuccessfulLogin()
132 {
133 $this->assertTrue($this->loginManager->canLogin($this->server));
134
135 $this->loginManager->handleSuccessfulLogin($this->server);
136 $this->assertTrue($this->loginManager->canLogin($this->server));
137 }
138
139 /**
140 * Erase failure records after successfully logging in from this IP
141 */
142 public function testHandleSuccessfulLoginAfterFailure()
143 {
144 $this->loginManager->handleFailedLogin($this->server);
44acf706
V
145 $this->assertTrue($this->loginManager->canLogin($this->server));
146
147 $this->loginManager->handleSuccessfulLogin($this->server);
b49a04f7 148 $this->loginManager->handleFailedLogin($this->server);
44acf706 149 $this->assertTrue($this->loginManager->canLogin($this->server));
44acf706
V
150 }
151
152 /**
153 * The IP is not banned
154 */
155 public function testCanLoginIpNotBanned()
156 {
157 $this->assertTrue($this->loginManager->canLogin($this->server));
158 }
159
c689e108
V
160 /**
161 * Generate a token depending on the user credentials and client IP
162 */
163 public function testGenerateStaySignedInToken()
164 {
704637bf 165 $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
c689e108
V
166
167 $this->assertEquals(
704637bf 168 sha1($this->passwordHash . $this->clientIpAddress . $this->salt),
c689e108
V
169 $this->loginManager->getStaySignedInToken()
170 );
171 }
704637bf 172
d9ba1cdd
A
173 /**
174 * Generate a token depending on the user credentials with session protected disabled
175 */
176 public function testGenerateStaySignedInTokenSessionProtectionDisabled()
177 {
178 $this->configManager->set('security.session_protection_disabled', true);
179 $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
180
181 $this->assertEquals(
182 sha1($this->passwordHash . $this->salt),
183 $this->loginManager->getStaySignedInToken()
184 );
185 }
186
704637bf
V
187 /**
188 * Check user login - Shaarli has not yet been configured
189 */
190 public function testCheckLoginStateNotConfigured()
191 {
192 $configManager = new \FakeConfigManager([
193 'resource.ban_file' => $this->banFile,
194 ]);
b49a04f7 195 $loginManager = new LoginManager($configManager, null);
704637bf
V
196 $loginManager->checkLoginState([], '');
197
198 $this->assertFalse($loginManager->isLoggedIn());
199 }
200
201 /**
202 * Check user login - the client cookie does not match the server token
203 */
204 public function testCheckLoginStateStaySignedInWithInvalidToken()
205 {
8edd7f15
V
206 // simulate a previous login
207 $this->session = [
208 'ip' => $this->clientIpAddress,
209 'expires_on' => time() + 100,
210 ];
704637bf
V
211 $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
212 $this->cookie[LoginManager::$STAY_SIGNED_IN_COOKIE] = 'nope';
213
214 $this->loginManager->checkLoginState($this->cookie, $this->clientIpAddress);
215
8edd7f15
V
216 $this->assertTrue($this->loginManager->isLoggedIn());
217 $this->assertTrue(empty($this->session['username']));
704637bf
V
218 }
219
220 /**
221 * Check user login - the client cookie matches the server token
222 */
223 public function testCheckLoginStateStaySignedInWithValidToken()
224 {
225 $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
226 $this->cookie[LoginManager::$STAY_SIGNED_IN_COOKIE] = $this->loginManager->getStaySignedInToken();
227
228 $this->loginManager->checkLoginState($this->cookie, $this->clientIpAddress);
229
230 $this->assertTrue($this->loginManager->isLoggedIn());
8edd7f15
V
231 $this->assertEquals($this->login, $this->session['username']);
232 $this->assertEquals($this->clientIpAddress, $this->session['ip']);
704637bf
V
233 }
234
235 /**
236 * Check user login - the session has expired
237 */
238 public function testCheckLoginStateSessionExpired()
239 {
240 $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
241 $this->session['expires_on'] = time() - 100;
242
243 $this->loginManager->checkLoginState($this->cookie, $this->clientIpAddress);
244
245 $this->assertFalse($this->loginManager->isLoggedIn());
246 }
247
248 /**
249 * Check user login - the remote client IP has changed
250 */
251 public function testCheckLoginStateClientIpChanged()
252 {
253 $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
254
255 $this->loginManager->checkLoginState($this->cookie, '10.7.157.98');
256
257 $this->assertFalse($this->loginManager->isLoggedIn());
258 }
259
260 /**
261 * Check user credentials - wrong login supplied
262 */
263 public function testCheckCredentialsWrongLogin()
264 {
265 $this->assertFalse(
266 $this->loginManager->checkCredentials('', '', 'b4dl0g1n', $this->password)
267 );
268 }
269
270 /**
271 * Check user credentials - wrong password supplied
272 */
273 public function testCheckCredentialsWrongPassword()
274 {
275 $this->assertFalse(
276 $this->loginManager->checkCredentials('', '', $this->login, 'b4dp455wd')
277 );
278 }
279
280 /**
281 * Check user credentials - wrong login and password supplied
282 */
283 public function testCheckCredentialsWrongLoginAndPassword()
284 {
285 $this->assertFalse(
286 $this->loginManager->checkCredentials('', '', 'b4dl0g1n', 'b4dp455wd')
287 );
288 }
289
290 /**
291 * Check user credentials - correct login and password supplied
292 */
293 public function testCheckCredentialsGoodLoginAndPassword()
294 {
295 $this->assertTrue(
296 $this->loginManager->checkCredentials('', '', $this->login, $this->password)
297 );
298 }
44acf706 299}