3 namespace Friendica\Model\User;
6 use Friendica\Core\Config\IConfig;
9 * Interacting with the Friendica Cookie of a user
13 /** @var int Default expire duration in days */
14 const DEFAULT_EXPIRE = 7;
15 /** @var string The name of the Friendica cookie */
16 const NAME = 'Friendica';
17 /** @var string The path of the Friendica cookie */
19 /** @var string The domain name of the Friendica cookie */
21 /** @var bool True, if the cookie should only be accessible through HTTP */
22 const HTTPONLY = true;
24 /** @var string The remote address of this node */
25 private $remoteAddr = '0.0.0.0';
26 /** @var bool True, if the connection is ssl enabled */
27 private $sslEnabled = false;
28 /** @var string The private key of this Friendica node */
29 private $sitePrivateKey;
30 /** @var int The default cookie lifetime */
31 private $lifetime = self::DEFAULT_EXPIRE * 24 * 60 * 60;
32 /** @var array The $_COOKIE array */
35 public function __construct(IConfig $config, App\BaseURL $baseURL, array $server = [], array $cookie = [])
37 if (!empty($server['REMOTE_ADDR'])) {
38 $this->remoteAddr = $server['REMOTE_ADDR'];
41 $this->sslEnabled = $baseURL->getSSLPolicy() === App\BaseURL::SSL_POLICY_FULL;
42 $this->sitePrivateKey = $config->get('system', 'site_prvkey');
44 $authCookieDays = $config->get('system', 'auth_cookie_lifetime',
45 self::DEFAULT_EXPIRE);
46 $this->lifetime = $authCookieDays * 24 * 60 * 60;
47 $this->cookie = $cookie;
51 * Checks if the Friendica cookie is set for a user
53 * @param string $hash The cookie hash
54 * @param string $password The user password
55 * @param string $privateKey The private Key of the user
57 * @return boolean True, if the cookie is set
60 public function check(string $hash, string $password, string $privateKey)
63 $this->getHash($password, $privateKey),
69 * Set the Friendica cookie for a user
71 * @param int $uid The user id
72 * @param string $password The user password
73 * @param string $privateKey The user private key
74 * @param int|null $seconds optional the seconds
78 public function set(int $uid, string $password, string $privateKey, int $seconds = null)
80 if (!isset($seconds)) {
81 $seconds = $this->lifetime + time();
82 } elseif (isset($seconds) && $seconds != 0) {
83 $seconds = $seconds + time();
86 $value = json_encode([
88 'hash' => $this->getHash($password, $privateKey),
89 'ip' => $this->remoteAddr,
92 return $this->setCookie(self::NAME, $value, $seconds, $this->sslEnabled);
96 * Returns the data of the Friendicas user cookie
98 * @return mixed|null The JSON data, null if not set
100 public function getData()
102 // When the "Friendica" cookie is set, take the value to authenticate and renew the cookie.
103 if (isset($this->cookie[self::NAME])) {
104 $data = json_decode($this->cookie[self::NAME]);
114 * Clears the Friendica cookie of this user after leaving the page
116 public function clear()
118 // make sure cookie is deleted on browser close, as a security measure
119 return $this->setCookie(self::NAME, '', -3600, $this->sslEnabled);
123 * Calculate the hash that is needed for the Friendica cookie
125 * @param string $password The user password
126 * @param string $privateKey The private key of the user
128 * @return string Hashed data
130 private function getHash(string $password, string $privateKey)
134 hash_hmac('sha256', $password, $privateKey),
135 $this->sitePrivateKey
140 * Send a cookie - protected, internal function for test-mocking possibility
142 * @link https://php.net/manual/en/function.setcookie.php
144 * @param string $name
145 * @param string $value [optional]
146 * @param int $expire [optional]
147 * @param bool $secure [optional]
149 * @return bool If output exists prior to calling this function,
152 protected function setCookie(string $name, string $value = null, int $expire = null,
155 return setcookie($name, $value, $expire, self::PATH, self::DOMAIN, $secure, self::HTTPONLY);