]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - tests/security/SessionManagerTest.php
Compatibility with PHPUnit 9
[github/shaarli/Shaarli.git] / tests / security / SessionManagerTest.php
1 <?php
2
3 namespace Shaarli\Security;
4
5 use Shaarli\TestCase;
6
7 /**
8 * Test coverage for SessionManager
9 */
10 class SessionManagerTest extends TestCase
11 {
12 /** @var array Session ID hashes */
13 protected static $sidHashes = null;
14
15 /** @var \FakeConfigManager ConfigManager substitute for testing */
16 protected $conf = null;
17
18 /** @var array $_SESSION array for testing */
19 protected $session = [];
20
21 /** @var SessionManager Server-side session management abstraction */
22 protected $sessionManager = null;
23
24 /**
25 * Assign reference data
26 */
27 public static function setUpBeforeClass(): void
28 {
29 self::$sidHashes = \ReferenceSessionIdHashes::getHashes();
30 }
31
32 /**
33 * Initialize or reset test resources
34 */
35 protected function setUp(): void
36 {
37 $this->conf = new \FakeConfigManager([
38 'credentials.login' => 'johndoe',
39 'credentials.salt' => 'salt',
40 'security.session_protection_disabled' => false,
41 ]);
42 $this->session = [];
43 $this->sessionManager = new SessionManager($this->session, $this->conf, 'session_path');
44 }
45
46 /**
47 * Generate a session token
48 */
49 public function testGenerateToken()
50 {
51 $token = $this->sessionManager->generateToken();
52
53 $this->assertEquals(1, $this->session['tokens'][$token]);
54 $this->assertEquals(40, strlen($token));
55 }
56
57 /**
58 * Check a session token
59 */
60 public function testCheckToken()
61 {
62 $token = '4dccc3a45ad9d03e5542b90c37d8db6d10f2b38b';
63 $session = [
64 'tokens' => [
65 $token => 1,
66 ],
67 ];
68 $sessionManager = new SessionManager($session, $this->conf, 'session_path');
69
70 // check and destroy the token
71 $this->assertTrue($sessionManager->checkToken($token));
72 $this->assertFalse(isset($session['tokens'][$token]));
73
74 // ensure the token has been destroyed
75 $this->assertFalse($sessionManager->checkToken($token));
76 }
77
78 /**
79 * Generate and check a session token
80 */
81 public function testGenerateAndCheckToken()
82 {
83 $token = $this->sessionManager->generateToken();
84
85 // ensure a token has been generated
86 $this->assertEquals(1, $this->session['tokens'][$token]);
87 $this->assertEquals(40, strlen($token));
88
89 // check and destroy the token
90 $this->assertTrue($this->sessionManager->checkToken($token));
91 $this->assertFalse(isset($this->session['tokens'][$token]));
92
93 // ensure the token has been destroyed
94 $this->assertFalse($this->sessionManager->checkToken($token));
95 }
96
97 /**
98 * Check an invalid session token
99 */
100 public function testCheckInvalidToken()
101 {
102 $this->assertFalse($this->sessionManager->checkToken('4dccc3a45ad9d03e5542b90c37d8db6d10f2b38b'));
103 }
104
105 /**
106 * Test SessionManager::checkId with a valid ID - TEST ALL THE HASHES!
107 *
108 * This tests extensively covers all hash algorithms / bit representations
109 */
110 public function testIsAnyHashSessionIdValid()
111 {
112 foreach (self::$sidHashes as $algo => $bpcs) {
113 foreach ($bpcs as $bpc => $hash) {
114 $this->assertTrue(SessionManager::checkId($hash));
115 }
116 }
117 }
118
119 /**
120 * Test checkId with a valid ID - SHA-1 hashes
121 */
122 public function testIsSha1SessionIdValid()
123 {
124 $this->assertTrue(SessionManager::checkId(sha1('shaarli')));
125 }
126
127 /**
128 * Test checkId with a valid ID - SHA-256 hashes
129 */
130 public function testIsSha256SessionIdValid()
131 {
132 $this->assertTrue(SessionManager::checkId(hash('sha256', 'shaarli')));
133 }
134
135 /**
136 * Test checkId with a valid ID - SHA-512 hashes
137 */
138 public function testIsSha512SessionIdValid()
139 {
140 $this->assertTrue(SessionManager::checkId(hash('sha512', 'shaarli')));
141 }
142
143 /**
144 * Test checkId with invalid IDs.
145 */
146 public function testIsSessionIdInvalid()
147 {
148 $this->assertFalse(SessionManager::checkId(''));
149 $this->assertFalse(SessionManager::checkId([]));
150 $this->assertFalse(
151 SessionManager::checkId('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=')
152 );
153 }
154
155 /**
156 * Store login information after a successful login
157 */
158 public function testStoreLoginInfo()
159 {
160 $this->sessionManager->storeLoginInfo('ip_id');
161
162 $this->assertGreaterThan(time(), $this->session['expires_on']);
163 $this->assertEquals('ip_id', $this->session['ip']);
164 $this->assertEquals('johndoe', $this->session['username']);
165 }
166
167 /**
168 * Extend a server-side session by SessionManager::$SHORT_TIMEOUT
169 */
170 public function testExtendSession()
171 {
172 $this->sessionManager->extendSession();
173
174 $this->assertGreaterThan(time(), $this->session['expires_on']);
175 $this->assertLessThanOrEqual(
176 time() + SessionManager::$SHORT_TIMEOUT,
177 $this->session['expires_on']
178 );
179 }
180
181 /**
182 * Extend a server-side session by SessionManager::$LONG_TIMEOUT
183 */
184 public function testExtendSessionStaySignedIn()
185 {
186 $this->sessionManager->setStaySignedIn(true);
187 $this->sessionManager->extendSession();
188
189 $this->assertGreaterThan(time(), $this->session['expires_on']);
190 $this->assertGreaterThan(
191 time() + SessionManager::$LONG_TIMEOUT - 10,
192 $this->session['expires_on']
193 );
194 $this->assertLessThanOrEqual(
195 time() + SessionManager::$LONG_TIMEOUT,
196 $this->session['expires_on']
197 );
198 }
199
200 /**
201 * Unset session variables after logging out
202 */
203 public function testLogout()
204 {
205 $this->session = [
206 'ip' => 'ip_id',
207 'expires_on' => time() + 1000,
208 'username' => 'johndoe',
209 'visibility' => 'public',
210 'untaggedonly' => true,
211 ];
212 $this->sessionManager->logout();
213
214 $this->assertArrayNotHasKey('ip', $this->session);
215 $this->assertArrayNotHasKey('expires_on', $this->session);
216 $this->assertArrayNotHasKey('username', $this->session);
217 $this->assertArrayNotHasKey('visibility', $this->session);
218 $this->assertArrayHasKey('untaggedonly', $this->session);
219 $this->assertTrue($this->session['untaggedonly']);
220 }
221
222 /**
223 * The session is active and expiration time has been reached
224 */
225 public function testHasExpiredTimeElapsed()
226 {
227 $this->session['expires_on'] = time() - 10;
228
229 $this->assertTrue($this->sessionManager->hasSessionExpired());
230 }
231
232 /**
233 * The session is active and expiration time has not been reached
234 */
235 public function testHasNotExpired()
236 {
237 $this->session['expires_on'] = time() + 1000;
238
239 $this->assertFalse($this->sessionManager->hasSessionExpired());
240 }
241
242 /**
243 * Session hijacking protection is disabled, we assume the IP has not changed
244 */
245 public function testHasClientIpChangedNoSessionProtection()
246 {
247 $this->conf->set('security.session_protection_disabled', true);
248
249 $this->assertFalse($this->sessionManager->hasClientIpChanged(''));
250 }
251
252 /**
253 * The client IP identifier has not changed
254 */
255 public function testHasClientIpChangedNope()
256 {
257 $this->session['ip'] = 'ip_id';
258 $this->assertFalse($this->sessionManager->hasClientIpChanged('ip_id'));
259 }
260
261 /**
262 * The client IP identifier has changed
263 */
264 public function testHasClientIpChanged()
265 {
266 $this->session['ip'] = 'ip_id_one';
267 $this->assertTrue($this->sessionManager->hasClientIpChanged('ip_id_two'));
268 }
269
270 /**
271 * Test creating an entry in the session array
272 */
273 public function testSetSessionParameterCreate(): void
274 {
275 $this->sessionManager->setSessionParameter('abc', 'def');
276
277 static::assertSame('def', $this->session['abc']);
278 }
279
280 /**
281 * Test updating an entry in the session array
282 */
283 public function testSetSessionParameterUpdate(): void
284 {
285 $this->session['abc'] = 'ghi';
286
287 $this->sessionManager->setSessionParameter('abc', 'def');
288
289 static::assertSame('def', $this->session['abc']);
290 }
291
292 /**
293 * Test updating an entry in the session array with null value
294 */
295 public function testSetSessionParameterUpdateNull(): void
296 {
297 $this->session['abc'] = 'ghi';
298
299 $this->sessionManager->setSessionParameter('abc', null);
300
301 static::assertArrayHasKey('abc', $this->session);
302 static::assertNull($this->session['abc']);
303 }
304
305 /**
306 * Test deleting an existing entry in the session array
307 */
308 public function testDeleteSessionParameter(): void
309 {
310 $this->session['abc'] = 'def';
311
312 $this->sessionManager->deleteSessionParameter('abc');
313
314 static::assertArrayNotHasKey('abc', $this->session);
315 }
316
317 /**
318 * Test deleting a non existent entry in the session array
319 */
320 public function testDeleteSessionParameterNotExisting(): void
321 {
322 $this->sessionManager->deleteSessionParameter('abc');
323
324 static::assertArrayNotHasKey('abc', $this->session);
325 }
326 }