GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

CurrentUser::saveCrsfTokenToSession()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace phpMyFAQ\User;
4
5
/**
6
 * Manages authentication process using PHP sessions.
7
 *
8
 * The CurrentUser class is an extension of the User class. It provides methods
9
 * manage user authentication using multiple database accesses. There are three
10
 * ways of making a new current user object, using the login(), getFromSession(),
11
 * getFromCookie() or manually. login(), getFromSession() and getFromCookie() may
12
 * be combined.
13
 *
14
 * This Source Code Form is subject to the terms of the Mozilla Public License,
15
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
16
 * obtain one at http://mozilla.org/MPL/2.0/.
17
 *
18
 * @package phpMyFAQ
19
 * @author Lars Tiedemann <[email protected]>
20
 * @author Thorsten Rinne <[email protected]>
21
 * @copyright 2005-2019 phpMyFAQ Team
22
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
23
 * @link https://www.phpmyfaq.de
24
 * @since 2005-09-28
25
 */
26
27
use phpMyFAQ\Configuration;
28
use phpMyFAQ\Db;
29
use phpMyFAQ\Session;
30
use phpMyFAQ\User;
31
32
if (!defined('IS_VALID_PHPMYFAQ')) {
33
    exit();
34
}
35
36
/* user defined constants */
37
define('SESSION_CURRENT_USER', 'CURRENT_USER');
38
define('SESSION_ID_TIMESTAMP', 'SESSION_TIMESTAMP');
39
40
/**
41
 * Class CurrentUser
42
 *
43
 * @package phpMyFAQ
44
 * @author Lars Tiedemann <[email protected]>
45
 * @author Thorsten Rinne <[email protected]>
46
 * @copyright 2005-2019 phpMyFAQ Team
47
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
48
 * @link https://www.phpmyfaq.de
49
 * @since 2005-09-28
50
 */
51
class CurrentUser extends User
52
{
53
    /**
54
     * true if CurrentUser is logged in, otherwise false.
55
     * @var bool
56
     */
57
    private $loggedIn = false;
58
59
    /**
60
     * Specifies the timeout for the session in minutes. If the session ID was
61
     * not updated for the last $this->_sessionTimeout minutes, the CurrentUser
62
     * will be logged out automatically if no cookie was set.
63
     * @var int
64
     */
65
    private $sessionTimeout = PMF_AUTH_TIMEOUT;
66
67
    /**
68
     * The Session class object
69
     * @var Session
70
     */
71
    private $session;
72
73
    /**
74
     * Specifies the timeout for the session-ID in minutes. If the session ID
75
     * was not updated for the last $this->_sessionIdTimeout minutes, it will
76
     * be updated. If set to 0, the session ID will be updated on every click.
77
     * The session ID timeout must not be greater than Session timeout.
78
     * @var int
79
     */
80
    private $sessionIdTimeout = 1;
81
82
    /**
83
     * LDAP configuration if available.
84
     * @var array
85
     */
86
    private $ldapConfig = [];
87
88
    /**
89
     * Remember me activated or deactivated.
90
     * @var bool
91
     */
92
    private $rememberMe = false;
93
94
    /**
95
     * Login successful or auth failure:
96
     * 1 -> success
97
     * 0 -> failure.
98
     * @var int
99
     */
100
    private $loginState = 1;
101
102
    /**
103
     * Number of failed login attempts
104
     * @var int
105
     */
106
    private $loginAttempts = 0;
107
108
    /**
109
     * Lockout time in seconds
110
     * @var integer
111
     */
112
    private $lockoutTime = 600;
113
114
    /**
115
     * Constructor.
116
     * @param Configuration $config
117
     */
118
    public function __construct(Configuration $config)
119
    {
120
        parent::__construct($config);
121
        $this->ldapConfig = $config->getLdapConfig();
122
        $this->session = new Session($config);
123
    }
124
125
    /**
126
     * Checks the given login and password in all auth-objects. Returns true
127
     * on success, otherwise false. Raises errors that can be checked using
128
     * the error() method. On success, the CurrentUser instance will be
129
     * labeled as logged in. The name of the successful auth container will
130
     * be stored in the user table. A new auth object may be added by using
131
     * addAuth() method. The given password must not be encrypted, since the
132
     * auth object takes care about the encryption method.
133
     *
134
     * @param string $login    Login name
135
     * @param string $password Password
136
     *
137
     * @return bool
138
     */
139
    public function login(string $login, string $password): bool
140
    {
141
        $optData = [];
142
        $loginError = $passwordError = $count = 0;
143
144
        // First check for brute force attack
145
        $this->getUserByLogin($login);
146
        if ($this->isFailedLastLoginAttempt()) {
147
            $this->errors[] = parent::ERROR_USER_TOO_MANY_FAILED_LOGINS;
148
            return false;
149
        }
150
151
        // Additional code for LDAP: user\\domain
152
        if ($this->config->get('ldap.ldapSupport') && $this->config->get('ldap.ldap_use_domain_prefix') &&
153
            '' !== $password) {
154
            // If LDAP configuration and ldap_use_domain_prefix is true
155
            // and LDAP credentials are provided (password is not empty)
156
            if (($pos = strpos($login, '\\')) !== false) {
157
                if ($pos !== 0) {
158
                    $optData['domain'] = substr($login, 0, $pos);
159
                }
160
161
                $login = substr($login, $pos + 1);
162
            }
163
        }
164
165
        // Additional code for SSO
166
        if ($this->config->get('security.ssoSupport') && isset($_SERVER['REMOTE_USER']) && '' === $password) {
167
            // if SSO configuration is enabled, REMOTE_USER is provided and we try to login using SSO (no password)
168 View Code Duplication
            if (($pos = strpos($login, '@')) !== false) {
169
                if ($pos !== 0) {
170
                    $login = substr($login, 0, $pos);
171
                }
172
            }
173 View Code Duplication
            if (($pos = strpos($login, '\\')) !== false) {
174
                if ($pos !== 0) {
175
                    $login = substr($login, $pos + 1);
176
                }
177
            }
178
        }
179
180
        // authenticate user by login and password
181
        foreach ($this->authContainer as $name => $auth) {
182
            ++$count;
183
184
            // $auth is an invalid Auth object, so continue
185
            if (!$this->checkAuth($auth)) {
186
                --$count;
187
                continue;
188
            }
189
190
            // $login does not exist, so continue
191
            if (!$auth->checkLogin($login, $optData)) {
192
                ++$loginError;
193
                continue;
194
            }
195
196
            // $login exists, but $pass is incorrect, so stop!
197
            if (!$auth->checkPassword($login, $password, $optData)) {
198
                ++$passwordError;
199
                // Don't stop, as other auth method could work:
200
                continue;
201
            }
202
203
            // but hey, this must be a valid match, so get user object
204
            $this->getUserByLogin($login);
205
            $this->loggedIn = true;
206
            $this->updateSessionId(true);
207
            $this->saveToSession();
208
            $this->saveCrsfTokenToSession();
209
210
            // save remember me cookie if set
211
            if (true === $this->rememberMe) {
212
                $rememberMe = sha1(session_id());
213
                $this->setRememberMe($rememberMe);
214
                $this->session->setCookie(
215
                    Session::PMF_COOKIE_NAME_REMEMBERME,
216
                    $rememberMe,
217
                    $_SERVER['REQUEST_TIME'] + PMF_REMEMBERME_EXPIRED_TIME
218
                );
219
            }
220
221
            // remember the auth container for administration
222
            $update = sprintf("
223
                UPDATE
224
                    %sfaquser
225
                SET
226
                    auth_source = '%s'
227
                WHERE
228
                    user_id = %d",
229
                Db::getTablePrefix(),
230
                $this->config->getDb()->escape($name),
231
                $this->getUserId()
232
            );
233
            $result = $this->config->getDb()->query($update);
234
            if (!$result) {
235
                $this->setSuccess(false);
236
                return false;
237
            }
238
239
            // Login successful
240
            $this->setSuccess(true);
241
            return true;
242
        }
243
244
        // raise errors and return false
245
        if ($loginError === $count) {
246
            $this->setSuccess(false);
247
            $this->errors[] = parent::ERROR_USER_INCORRECT_LOGIN;
248
        }
249
        if ($passwordError > 0) {
250
            $this->getUserByLogin($login);
251
            $this->setLoginAttempt();
252
            $this->errors[] = parent::ERROR_USER_INCORRECT_PASSWORD;
253
        }
254
255
        return false;
256
    }
257
258
    /**
259
     * Returns true if CurrentUser is logged in, otherwise false.
260
     * @return bool
261
     */
262
    public function isLoggedIn(): bool
263
    {
264
        return $this->loggedIn;
265
    }
266
267
    /**
268
     * Returns false if the CurrentUser object stored in the
269
     * session is valid and not timed out. There are two
270
     * parameters for session timeouts: $this->_sessionTimeout
271
     * and $this->_sessionIdTimeout.
272
     * @return bool
273
     */
274
    public function sessionIsTimedOut(): bool
275
    {
276
        if ($this->sessionTimeout <= $this->sessionAge()) {
277
            return true;
278
        }
279
        return false;
280
    }
281
282
    /**
283
     * Returns false if the session-ID is not timed out.
284
     *
285
     * @return bool
286
     */
287
    public function sessionIdIsTimedOut(): bool
288
    {
289
        if ($this->sessionIdTimeout <= $this->sessionAge()) {
290
            return true;
291
        }
292
        return false;
293
    }
294
295
    /**
296
     * Returns the age of the current session-ID in minutes.
297
     *
298
     * @return float
299
     */
300
    public function sessionAge(): float
301
    {
302
        if (!isset($_SESSION[SESSION_ID_TIMESTAMP])) {
303
            return 0;
304
        }
305
        return ($_SERVER['REQUEST_TIME'] - $_SESSION[SESSION_ID_TIMESTAMP])/60;
306
    }
307
308
    /**
309
     * Returns an associative array with session information stored
310
     * in the user table. The array has the following keys:
311
     * session_id, session_timestamp and ip.
312
     * @return array
313
     */
314
    public function getSessionInfo(): array
315
    {
316
        $select = sprintf('
317
            SELECT
318
                session_id,
319
                session_timestamp,
320
                ip,
321
                success
322
            FROM
323
                %sfaquser
324
            WHERE
325
                user_id = %d',
326
            Db::getTablePrefix(),
327
            $this->getUserId()
328
        );
329
330
        $res = $this->config->getDb()->query($select);
331
        if (!$res or $this->config->getDb()->numRows($res) != 1) {
332
            return [];
333
        }
334
335
        return $this->config->getDb()->fetchArray($res);
336
    }
337
338
    /**
339
     * Updates the session-ID, does not care about time outs.
340
     * Stores session information in the user table: session_id,
341
     * session_timestamp and ip.
342
     * Optionally it should update the 'last login' time.
343
     * Returns true on success, otherwise false.
344
     *
345
     * @param bool $updateLastLogin Update the last login time?
346
     *
347
     * @return bool
348
     */
349
    public function updateSessionId(bool $updateLastLogin = false): bool
350
    {
351
        // renew the session-ID
352
        $oldSessionId = session_id();
353
        if (session_regenerate_id(true)) {
354
            $sessionPath = session_save_path();
355
            if (strpos($sessionPath, ';') !== false) {
356
                $sessionPath = substr($sessionPath, strpos($sessionPath, ';') + 1);
357
            }
358
            $sessionFilename = $sessionPath.'/sess_'.$oldSessionId;
359
            if (@file_exists($sessionFilename)) {
360
                @unlink($sessionFilename);
361
            }
362
        }
363
        // store session-ID age
364
        $_SESSION[SESSION_ID_TIMESTAMP] = $_SERVER['REQUEST_TIME'];
365
        // save session information in user table
366
        $update = sprintf("
367
            UPDATE
368
                %sfaquser
369
            SET
370
                session_id = '%s',
371
                session_timestamp = %d,
372
                %s
373
                ip = '%s'
374
            WHERE
375
                user_id = %d",
376
            Db::getTablePrefix(),
377
            session_id(),
378
            $_SERVER['REQUEST_TIME'],
379
            $updateLastLogin ? "last_login = '".date('YmdHis', $_SERVER['REQUEST_TIME'])."'," : '',
380
            $_SERVER['REMOTE_ADDR'],
381
            $this->getUserId()
382
        );
383
384
        $res = $this->config->getDb()->query($update);
385
        if (!$res) {
386
            $this->errors[] = $this->config->getDb()->error();
387
388
            return false;
389
        }
390
391
        return true;
392
    }
393
394
    /**
395
     * Saves the CurrentUser into the session. This method
396
     * may be called after a successful login.
397
     * @return void
398
     */
399
    public function saveToSession()
400
    {
401
        $_SESSION[SESSION_CURRENT_USER] = $this->getUserId();
402
    }
403
404
    /**
405
     * Deletes the CurrentUser from the session. The user
406
     * will be logged out. Return true on success, otherwise false.
407
     * @param bool $deleteCookie
408
     * @return bool
409
     */
410
    public function deleteFromSession(bool $deleteCookie = false): bool
411
    {
412
        // delete CSRF Token
413
        $this->deleteCsrfTokenFromSession();
414
415
        // delete CurrentUser object from session
416
        $_SESSION[SESSION_CURRENT_USER] = null;
417
        unset($_SESSION[SESSION_CURRENT_USER]);
418
419
        // log CurrentUser out
420
        $this->loggedIn = false;
421
422
        // delete session-ID
423
        $update = sprintf('
424
            UPDATE
425
                %sfaquser
426
            SET
427
                session_id = NULL
428
                %s
429
            WHERE
430
                user_id = %d',
431
                Db::getTablePrefix(),
432
                $deleteCookie ? ', remember_me = NULL' : '',
433
                $this->getUserId()
434
        );
435
436
        $res = $this->config->getDb()->query($update);
437
438
        if (!$res) {
439
            $this->errors[] = $this->config->getDb()->error();
440
441
            return false;
442
        }
443
444
        if ($deleteCookie) {
445
            $this->session->setCookie(Session::PMF_COOKIE_NAME_REMEMBERME);
446
        }
447
448
        session_destroy();
449
450
        return true;
451
    }
452
453
    /**
454
     * This static method returns a valid CurrentUser object if there is one
455
     * in the session that is not timed out. The session-ID is updated if
456
     * necessary. The CurrentUser will be removed from the session, if it is
457
     * timed out. If there is no valid CurrentUser in the session or the
458
     * session is timed out, null will be returned. If the session data is
459
     * correct, but there is no user found in the user table, false will be
460
     * returned. On success, a valid CurrentUser object is returned.
461
     * @static
462
     * @param Configuration $config
463
     * @return null|CurrentUser
464
     */
465
    public static function getFromSession(Configuration $config)
466
    {
467
        // there is no valid user object in session
468
        if (!isset($_SESSION[SESSION_CURRENT_USER]) || !isset($_SESSION[SESSION_ID_TIMESTAMP])) {
469
            return null;
470
        }
471
472
        // create a new CurrentUser object
473
        $user = new self($config);
474
        $user->getUserById($_SESSION[SESSION_CURRENT_USER]);
475
476
        // user object is timed out
477
        if ($user->sessionIsTimedOut()) {
478
            $user->deleteFromSession();
479
            $user->errors[] = 'Session timed out.';
480
481
            return null;
482
        }
483
        // session-id not found in user table
484
        $session_info = $user->getSessionInfo();
485
        $session_id = (isset($session_info['session_id']) ? $session_info['session_id'] : '');
486
        if ($session_id == '' || $session_id != session_id()) {
487
            return null;
488
        }
489
        // check ip
490
        if ($config->get('security.ipCheck') &&
491
            $session_info['ip'] != $_SERVER['REMOTE_ADDR']) {
492
            return null;
493
        }
494
        // session-id needs to be updated
495
        if ($user->sessionIdIsTimedOut()) {
496
            $user->updateSessionId();
497
        }
498
        // user is now logged in
499
        $user->loggedIn = true;
500
        // save current user to session and return the instance
501
        $user->saveToSession();
502
503
        return $user;
504
    }
505
506
    /**
507
     * This static method returns a valid CurrentUser object if there is one
508
     * in the cookie that is not timed out. The session-ID is updated then.
509
     * The CurrentUser will be removed from the session, if it is
510
     * timed out. If there is no valid CurrentUser in the cookie or the
511
     * cookie is timed out, null will be returned. If the cookie is correct,
512
     * but there is no user found in the user table, false will be returned.
513
     * On success, a valid CurrentUser object is returned.
514
     *
515
     * @static
516
     *
517
     * @param Configuration $config
518
     *
519
     * @return null|CurrentUser
520
     */
521
    public static function getFromCookie(Configuration $config)
522
    {
523
        if (!isset($_COOKIE[Session::PMF_COOKIE_NAME_REMEMBERME])) {
524
            return null;
525
        }
526
527
        // create a new CurrentUser object
528
        $user = new self($config);
529
        $user->getUserByCookie($_COOKIE[Session::PMF_COOKIE_NAME_REMEMBERME]);
530
531
        if (-1 === $user->getUserId()) {
532
            return null;
533
        }
534
535
        // sessionId needs to be updated
536
        $user->updateSessionId(true);
537
        // user is now logged in
538
        $user->loggedIn = true;
539
        // save current user to session and return the instance
540
        $user->saveToSession();
541
        // add CSRF token to session
542
        $user->saveCrsfTokenToSession();
543
544
        return $user;
545
    }
546
547
    /**
548
     * Sets the number of minutes when the current user stored in
549
     * the session gets invalid.
550
     *
551
     * @param float $timeout Timeout
552
     */
553
    public function setSessionTimeout($timeout)
554
    {
555
        $this->sessionTimeout = abs($timeout);
0 ignored issues
show
Documentation Bug introduced by
It seems like abs($timeout) can also be of type double. However, the property $sessionTimeout is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
556
    }
557
558
    /**
559
     * Sets the number of minutes when the session-ID needs to be
560
     * updated. By setting the session-ID timeout to zero, the
561
     * session-ID will be updated on each click.
562
     *
563
     * @param float $timeout Timeout
564
     */
565
    public function setSessionIdTimeout($timeout)
566
    {
567
        $this->sessionIdTimeout = abs($timeout);
0 ignored issues
show
Documentation Bug introduced by
It seems like abs($timeout) can also be of type double. However, the property $sessionIdTimeout is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
568
    }
569
570
    /**
571
     * Enables the remember me decision.
572
     */
573
    public function enableRememberMe()
574
    {
575
        $this->rememberMe = true;
576
    }
577
578
    /**
579
     * Saves remember me token in the database.
580
     *
581
     * @param string $rememberMe
582
     *
583
     * @return bool
584
     */
585
    protected function setRememberMe($rememberMe)
586
    {
587
        $update = sprintf("
588
            UPDATE
589
                %sfaquser
590
            SET
591
                remember_me = '%s'
592
            WHERE
593
                user_id = %d",
594
            Db::getTablePrefix(),
595
            $this->config->getDb()->escape($rememberMe),
596
            $this->getUserId()
597
        );
598
599
        return $this->config->getDb()->query($update);
600
    }
601
602
    /**
603
     * Sets login success/failure.
604
     *
605
     * @param bool $success
606
     *
607
     * @return bool
608
     */
609
    protected function setSuccess($success)
610
    {
611
        $this->loginState = (int)$success;
612
        $this->loginAttempts = 0;
613
614
        $update = sprintf('
615
            UPDATE
616
                %sfaquser
617
            SET
618
                success = %d,
619
                login_attempts = %d
620
            WHERE
621
                user_id = %d',
622
            Db::getTablePrefix(),
623
            $this->loginState,
624
            $this->loginAttempts,
625
            $this->getUserId()
626
        );
627
628
        return $this->config->getDb()->query($update);
629
    }
630
631
    /**
632
     * Sets IP and session timestamp plus lockout time, success flag to
633
     * false.
634
     *
635
     * @return mixed
636
     */
637 View Code Duplication
    protected function setLoginAttempt()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
638
    {
639
        $this->loginAttempts++;
640
641
        $update = sprintf("
642
            UPDATE
643
                %sfaquser
644
            SET
645
                session_timestamp ='%s',
646
                ip = '%s',
647
                success = 0,
648
                login_attempts = login_attempts + 1
649
            WHERE
650
                user_id = %d",
651
            Db::getTablePrefix(),
652
            $_SERVER['REQUEST_TIME'],
653
            $_SERVER['REMOTE_ADDR'],
654
            $this->getUserId()
655
        );
656
657
        return $this->config->getDb()->query($update);
658
    }
659
660
    /**
661
     * Checks if the last login attempt from current user failed.
662
     *
663
     * @return bool
664
     */
665
    protected function isFailedLastLoginAttempt()
666
    {
667
        $select = sprintf("
668
            SELECT
669
                session_timestamp,
670
                ip,
671
                success,
672
                login_attempts
673
            FROM
674
                %sfaquser
675
            WHERE
676
                user_id = %d
677
            AND
678
                ('%d' - session_timestamp) <= %d
679
            AND
680
                ip = '%s'
681
            AND
682
                success = 0
683
            AND
684
                login_attempts > 5",
685
            Db::getTablePrefix(),
686
            $this->getUserId(),
687
            $_SERVER['REQUEST_TIME'],
688
            $this->lockoutTime,
689
            $_SERVER['REMOTE_ADDR']
690
        );
691
692
        $result = $this->config->getDb()->query($select);
693
        if ($this->config->getDb()->numRows($result) !== 0) {
694
            return true;
695
        } else {
696
            return false;
697
        }
698
    }
699
700
    /**
701
     * Returns the CSRF token from session.
702
     *
703
     * @return string
704
     */
705
    public function getCsrfTokenFromSession()
706
    {
707
        return $_SESSION['phpmyfaq_csrf_token'];
708
    }
709
710
    /**
711
     * Save CSRF token to session.
712
     */
713
    public function saveCrsfTokenToSession()
714
    {
715
        if (!isset($_SESSION['phpmyfaq_csrf_token'])) {
716
            $_SESSION['phpmyfaq_csrf_token'] = $this->createCsrfToken();
717
        }
718
    }
719
720
    /**
721
     * Deletes CSRF token from session.
722
     */
723
    protected function deleteCsrfTokenFromSession()
724
    {
725
        unset($_SESSION['phpmyfaq_csrf_token']);
726
    }
727
728
    /**
729
     * Creates a CSRF token.
730
     *
731
     * @return string
732
     */
733
    private function createCsrfToken()
734
    {
735
        return sha1(microtime().$this->getLogin());
736
    }
737
}
738