/** * set/update logged in cookie by character model * -> store validation data in DB * @param Model\CharacterModel $character */ protected function setLoginCookie(Model\CharacterModel $character) { if ($this->getCookieState()) { $expireSeconds = (int) $this->getF3()->get('PATHFINDER.LOGIN.COOKIE_EXPIRE'); $expireSeconds *= 24 * 60 * 60; $timezone = new \DateTimeZone($this->getF3()->get('TZ')); $expireTime = new \DateTime('now', $timezone); // add cookie expire time $expireTime->add(new \DateInterval('PT' . $expireSeconds . 'S')); // unique "selector" -> to facilitate database look-ups (small size) // -> This is preferable to simply using the database id field, // which leaks the number of active users on the application $selector = bin2hex(mcrypt_create_iv(12, MCRYPT_DEV_URANDOM)); // generate unique "validator" (strong encryption) // -> plaintext set to user (cookie), hashed version of this in DB $size = mcrypt_get_iv_size(MCRYPT_CAST_256, MCRYPT_MODE_CFB); $validator = bin2hex(mcrypt_create_iv($size, MCRYPT_DEV_URANDOM)); // generate unique cookie token $token = hash('sha256', $validator); // get unique cookie name for this character $name = $character->getCookieName(); $authData = ['characterId' => $character, 'selector' => $selector, 'token' => $token, 'expires' => $expireTime->format('Y-m-d H:i:s')]; $authenticationModel = $character->rel('characterAuthentications'); $authenticationModel->copyfrom($authData); $authenticationModel->save(); $cookieValue = implode(':', [$selector, $validator]); // get cookie name -> save new one OR update existing cookie $cookieName = 'COOKIE.' . self::COOKIE_PREFIX_CHARACTER . '_' . $name; $this->getF3()->set($cookieName, $cookieValue, $expireSeconds); } }