ILIAS  trunk Revision v13.0_alpha-52-g21c366bbdd4
class.ilAuthSession.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
23
25{
26 private const string SESSION_AUTH_AUTHENTICATED = '_authsession_authenticated';
27 private const string SESSION_AUTH_USER_ID = '_authsession_user_id';
28 private const string SESSION_AUTH_EXPIRED = '_authsession_expired';
29
30 private static ?ilAuthSession $instance = null;
31
33
34 private string $id = '';
35 private int $user_id = 0;
36 private bool $expired = false;
37 private bool $authenticated = false;
38
39 private function __construct(ilLogger $logger)
40 {
41 $this->logger = $logger;
42 }
43
44 public static function getInstance(ilLogger $logger): self
45 {
46 return self::$instance ??= new self($logger);
47 }
48
49 protected function getLogger(): ilLogger
50 {
51 return $this->logger;
52 }
53
57 public function init(SubmittedSessionId $submitted_session_id): bool
58 {
59 if (session_status() === PHP_SESSION_ACTIVE) {
60 $this->getLogger()->error(__METHOD__ . ' called with active session.');
61 $this->getLogger()->logStack(ilLogLevel::ERROR);
62 return false;
63 }
64
65 session_start();
66
67 $this->setId(session_id());
68 $this->rejectForeignSessionIdIfUnknown($submitted_session_id);
69
70 $user_id = (int) (ilSession::get(self::SESSION_AUTH_USER_ID) ?? ANONYMOUS_USER_ID);
71 if ($user_id) {
72 $this->getLogger()->debug('Resuming old session for user: ' . $user_id);
73 $this->setUserId($user_id);
74 $this->expired = (bool) ilSession::get(self::SESSION_AUTH_EXPIRED);
75 $this->authenticated = (bool) ilSession::get(self::SESSION_AUTH_AUTHENTICATED);
76
77 $this->validateExpiration();
78 } else {
79 $this->getLogger()->debug('Started new session.');
81 $this->expired = false;
82 $this->authenticated = false;
83 }
84
85 return true;
86 }
87
91 public function isValid(): bool
92 {
93 return !$this->isExpired() && $this->isAuthenticated();
94 }
95
96 public function regenerateId(): void
97 {
98 $this->applySessionRotation(SessionRotationPolicy::Rotate);
99 }
100
105 public function logout(): void
106 {
107 $this->getLogger()->debug('Logout called for: ' . $this->getUserId());
108
109 $this->clearSessionPayload();
110
111 session_destroy();
112 session_start();
113
115 $this->applySessionRotation(SessionRotationPolicy::Rotate);
116 }
117
121 public function ensureAnonymousContext(): void
122 {
123 $this->getLogger()->debug(
124 'Ensure anonymous context for: ' . $this->getUserId()
125 );
127 }
128
132 public function onLoginSuccess(int $user_id): void
133 {
134 $this->setAuthenticated($user_id);
135 $this->applySessionRotation(SessionRotationPolicy::Rotate);
136 }
137
141 public function onSessionExpired(): void
142 {
144 $this->applySessionRotation(SessionRotationPolicy::Rotate);
145 }
146
150 public function isAuthenticated(): bool
151 {
152 return $this->authenticated || $this->user_id === ANONYMOUS_USER_ID;
153 }
154
155 private function setAuthenticated(int $a_user_id): void
156 {
157 $this->authenticated = true;
158 $this->user_id = $a_user_id;
159 ilSession::set(self::SESSION_AUTH_AUTHENTICATED, true);
160 ilSession::set(self::SESSION_AUTH_USER_ID, $a_user_id);
161 $this->setExpired(false);
162 }
163
164 public function isFullyAuthenticated(): bool
165 {
166 return $this->isValid() && $this->user_id !== ANONYMOUS_USER_ID && $this->user_id > 0;
167 }
168
169 public function isAnonymouslyAuthenticated(): bool
170 {
171 return $this->isValid() && $this->user_id === ANONYMOUS_USER_ID;
172 }
173
177 public function isExpired(): bool
178 {
179 return $this->expired && $this->user_id !== ANONYMOUS_USER_ID;
180 }
181
185 public function setExpired(bool $a_status): void
186 {
187 $this->expired = $a_status;
188 ilSession::set(self::SESSION_AUTH_EXPIRED, (int) $a_status);
189 }
190
194 public function setUserId(int $a_id): void
195 {
196 $this->user_id = $a_id;
197 }
198
202 public function getUserId(): int
203 {
204 return $this->user_id;
205 }
206
210 protected function validateExpiration(): bool
211 {
212 if ($this->isExpired()) {
213 // keep status
214 return false;
215 }
216
217 if (time() > ilSession::lookupExpireTime($this->getId())) {
218 $this->setExpired(true);
219 return false;
220 }
221
222 return true;
223 }
224
228 protected function setId(string $a_id): void
229 {
230 $this->id = $a_id;
231 }
232
236 public function getId(): string
237 {
238 return $this->id;
239 }
240
245 private function establishAnonymousAuthState(): void
246 {
247 if ($this->holdsLoggedInAccount()) {
248 $this->clearSessionPayload();
249 }
250
252 }
253
254 private function holdsLoggedInAccount(): bool
255 {
256 return $this->user_id > 0 && $this->user_id !== ANONYMOUS_USER_ID;
257 }
258
259 private function clearSessionPayload(): void
260 {
262 }
263
264 private function rejectForeignSessionIdIfUnknown(SubmittedSessionId $submitted_session_id): void
265 {
266 if (defined('IL_PHPUNIT_TEST')) {
267 return;
268 }
269
270 $submitted_id = $submitted_session_id->get();
271 if ($submitted_id === '' || $submitted_id !== session_id()) {
272 return;
273 }
274
275 if (!ilSession::exists($submitted_id)) {
277 }
278 }
279
281 {
282 $old_session_id = session_id();
283
284 session_regenerate_id(
285 $policy === SessionRotationPolicy::Rotate
286 );
287
288 $this->setId(session_id());
289
291 ? 'Session reject foreign id'
292 : 'Session regenerate id';
293 $this->getLogger()->info(
294 $label . ': [' . substr($old_session_id, 0, 5) . '] -> [' . substr($this->getId(), 0, 5) . ']'
295 );
296 }
297}
init(SubmittedSessionId $submitted_session_id)
Start auth session.
static getInstance(ilLogger $logger)
rejectForeignSessionIdIfUnknown(SubmittedSessionId $submitted_session_id)
setAuthenticated(int $a_user_id)
establishAnonymousAuthState()
Anonymous auth flags.
const string SESSION_AUTH_AUTHENTICATED
validateExpiration()
Check expired value of session.
onSessionExpired()
Transition an expired privileged session to anonymous.
const string SESSION_AUTH_EXPIRED
applySessionRotation(SessionRotationPolicy $policy)
ensureAnonymousContext()
Prepare the login screen: anonymous auth state in the current session (no destroy,...
__construct(ilLogger $logger)
isValid()
Check if current session is valid (authenticated and not expired)
isExpired()
Check if current is or was expired in last request.
getUserId()
Get authenticated user id.
setUserId(int $a_id)
Set authenticated user id.
setId(string $a_id)
Set id.
setExpired(bool $a_status)
Set session expired.
const string SESSION_AUTH_USER_ID
isAuthenticated()
Check if session is authenticated.
getId()
get session id
logout()
End the current auth context and establish an anonymous session.
static ilAuthSession $instance
onLoginSuccess(int $user_id)
Establish an authenticated session after successful login.
Component logger with individual log levels by component id.
static get(string $a_var)
static purge()
static exists(string $a_session_id)
static set(string $a_var, $a_val)
Set a value.
static lookupExpireTime(string $a_session_id)
Lookup expire time for a specific session.
const ANONYMOUS_USER_ID
Definition: constants.php:27
The session id a client sent with the current request.
SessionRotationPolicy
When and how the PHP session id is changed at a security boundary.
@ RejectForeign
Issue a new session id after login, logout, or expiry.