setHttpOnly(true) ->forgetMe(); } /** * Create the remember me component from the remember me cookie * * @return static */ public static function fromCookie() { $data = explode('|', $_COOKIE[static::COOKIE]); $iv = base64_decode(array_pop($data)); $tag = base64_decode(array_pop($data)); $select = (new Select()) ->from(static::TABLE) ->columns('*') ->where(['random_iv = ?' => bin2hex($iv)]); $rememberMe = new static(); $rs = $rememberMe->getDb()->select($select)->fetch(); if (! $rs) { throw new RuntimeException(sprintf( "No database entry found for IV '%s'", bin2hex($iv) )); } $rememberMe->aesCrypt = (new AesCrypt()) ->setKey(hex2bin($rs->passphrase)) ->setTag($tag) ->setIV($iv); $rememberMe->username = $rs->username; $rememberMe->encryptedPassword = $data[0]; return $rememberMe; } /** * Create the remember me component from the given username and password * * @param string $username * @param string $password * * @return static */ public static function fromCredentials($username, $password) { $aesCrypt = new AesCrypt(); $rememberMe = new static(); $rememberMe->encryptedPassword = $aesCrypt->encryptToBase64($password); $rememberMe->username = $username; $rememberMe->aesCrypt = $aesCrypt; return $rememberMe; } /** * Remove expired remember me information from the database */ public static function removeExpired() { $rememberMe = new static(); if (! $rememberMe->hasDb()) { return; } $rememberMe->getDb()->delete(static::TABLE, [ 'expires_at < NOW()' ]); } /** * Get the remember me cookie * * @return Cookie */ public function getCookie() { return (new Cookie(static::COOKIE)) ->setExpire($this->getExpiresAt()) ->setHttpOnly(true) ->setValue(implode('|', [ $this->encryptedPassword, base64_encode($this->aesCrypt->getTag()), base64_encode($this->aesCrypt->getIV()), ])); } /** * Get the timestamp when the cookie expires * * Defaults to now plus 30 days, if not set via {@link setExpiresAt()}. * * @return int */ public function getExpiresAt() { if ($this->expiresAt === null) { $this->expiresAt = time() + 60 * 60 * 24 * 30; } return $this->expiresAt; } /** * Set the timestamp when the cookie expires * * @param int $expiresAt * * @return $this */ public function setExpiresAt($expiresAt) { $this->expiresAt = $expiresAt; return $this; } /** * Authenticate via the remember me cookie * * @return bool * * @throws \Icinga\Exception\AuthenticationException */ public function authenticate() { $password = $this->aesCrypt->decryptFromBase64($this->encryptedPassword); $auth = Auth::getInstance(); $authChain = $auth->getAuthChain(); $authChain->setSkipExternalBackends(true); $user = new User($this->username); if (! $user->hasDomain()) { $user->setDomain(Config::app()->get('authentication', 'default_domain')); } $authenticated = $authChain->authenticate($user, $password); if ($authenticated) { $auth->setAuthenticated($user); } return $authenticated; } /** * Persist the remember me information into the database * * Any previous stored information is automatically removed. * * @param string|null $iv * * @return $this */ public function persist($iv = null) { if ($iv) { $this->remove($iv); } $this->getDb()->insert(static::TABLE, [ 'username' => $this->username, 'passphrase' => bin2hex($this->aesCrypt->getKey()), 'random_iv' => bin2hex($this->aesCrypt->getIV()), 'http_user_agent' => (new UserAgent)->getAgent(), 'expires_at' => date('Y-m-d H:i:s', $this->getExpiresAt()), 'ctime' => new Expression('NOW()'), 'mtime' => new Expression('NOW()') ]); return $this; } /** * Remove remember me information from the database * * @param string $iv * * @return $this */ public function remove($iv) { $this->getDb()->delete(static::TABLE, [ 'random_iv = ?' => bin2hex($iv) ]); return $this; } /** * Create renewed remember me cookie * * @return static New remember me cookie which has to be sent to the client */ public function renew() { return static::fromCredentials( $this->username, $this->aesCrypt->decryptFromBase64($this->encryptedPassword) ); } /** * Remove specific remember me information from the database * * @param string $username * * @param $iv * * @return $this */ public function removeSpecific($iv) { $this->getDb()->delete(static::TABLE, [ 'random_iv = ?' => $iv ]); return $this; } /** * Get all users using rememberme cookie * * @return array */ public static function getAllUser() { $rememberMe = new static(); if (! $rememberMe->hasDb()) { return []; } $select = (new Select()) ->from(static::TABLE) ->columns('username') ->groupBy('username'); return $rememberMe->getDb()->select($select)->fetchAll(); } /** * Get all rememberme cookies of the given user * * @param $username * * @return array */ public static function getAllByUsername($username) { $rememberMe = new static(); if (! $rememberMe->hasDb()) { return []; } $select = (new Select()) ->from(static::TABLE) ->columns(['http_user_agent', 'random_iv']) ->where(['username = ?' => $username]); return $rememberMe->getDb()->select($select)->fetchAll(); } /** * Get the encrypton/decryption instance * * @return AesCrypt */ public function getAesCrypt() { return $this->aesCrypt; } }