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