posts/plugins/login/vendor/birke/rememberme/src/Rememberme/Authenticator.php

294 lines
7.1 KiB
PHP

<?php
namespace Birke\Rememberme;
class Authenticator
{
/**
* @var string
*/
protected $cookieName = "PHP_REMEMBERME";
/**
* @var Cookie
*/
protected $cookie;
/**
* @var Storage\StorageInterface
*/
protected $storage;
/**
* Number of seconds in the future the cookie and storage will expire (defaults to 1 week)
* @var int
*/
protected $expireTime = 604800;
/**
* If the return from the storage was Birke\Rememberme\Storage\StorageInterface::TRIPLET_INVALID,
* this is set to true
* @var bool
*/
protected $lastLoginTokenWasInvalid = false;
/**
* If the login token was invalid, delete all login tokens of this user
* @var bool
*/
protected $cleanStoredTokensOnInvalidResult = true;
/**
* Additional salt to add more entropy when the tokens are stored as hashes.
* @var string
*/
protected $salt = "";
/**
* @param Storage\StorageInterface $storage
*/
public function __construct(Storage\StorageInterface $storage)
{
$this->storage = $storage;
$this->cookie = new Cookie();
}
/**
* Check Credentials from cookie. Returns false if login was not successful, credential string if it was successful
* @return bool|string
*/
public function login()
{
$cookieValues = $this->getCookieValues();
if (!$cookieValues) {
return false;
}
$loginResult = false;
switch ($this->storage->findTriplet($cookieValues[0], $cookieValues[1] . $this->salt, $cookieValues[2] . $this->salt)) {
case Storage\StorageInterface::TRIPLET_FOUND:
$expire = time() + $this->expireTime;
$newToken = $this->createToken();
$this->storage->replaceTriplet($cookieValues[0], $newToken . $this->salt, $cookieValues[2] . $this->salt, $expire);
$this->cookie->setCookie($this->cookieName, implode("|", array($cookieValues[0], $newToken, $cookieValues[2])), $expire);
$loginResult = $cookieValues[0];
break;
case Storage\StorageInterface::TRIPLET_INVALID:
$this->cookie->setCookie($this->cookieName, "", time() - $this->expireTime);
$this->lastLoginTokenWasInvalid = true;
if ($this->cleanStoredTokensOnInvalidResult) {
$this->storage->cleanAllTriplets($cookieValues[0]);
}
break;
}
return $loginResult;
}
/**
* @return bool
*/
public function cookieIsValid()
{
$cookieValues = $this->getCookieValues();
if (!$cookieValues) {
return false;
}
$state = $this->storage->findTriplet($cookieValues[0], $cookieValues[1] . $this->salt, $cookieValues[2] . $this->salt);
return $state == Storage\StorageInterface::TRIPLET_FOUND;
}
/**
* @param $credential
* @return $this
*/
public function createCookie($credential)
{
$newToken = $this->createToken();
$newPersistentToken = $this->createToken();
$expire = time() + $this->expireTime;
$this->storage->storeTriplet($credential, $newToken . $this->salt, $newPersistentToken . $this->salt, $expire);
$this->cookie->setCookie($this->cookieName, implode("|", array($credential, $newToken, $newPersistentToken)), $expire);
return $this;
}
/**
* Expire the rememberme cookie, unset $_COOKIE[$this->cookieName] value and
* remove current login triplet from storage.
* @param boolean $clearFromStorage
* @return boolean
*/
public function clearCookie($clearFromStorage = true)
{
if (empty($_COOKIE[$this->cookieName])) {
return false;
}
$cookieValues = explode("|", $_COOKIE[$this->cookieName], 3);
$this->cookie->setCookie($this->cookieName, "", time() - $this->expireTime);
unset($_COOKIE[$this->cookieName]);
if (!$clearFromStorage) {
return true;
}
if (count($cookieValues) < 3) {
return false;
}
$this->storage->cleanTriplet($cookieValues[0], $cookieValues[2] . $this->salt);
return true;
}
/**
* @return string
*/
public function getCookieName()
{
return $this->cookieName;
}
/**
* @param $name
* @return $this
*/
public function setCookieName($name)
{
$this->cookieName = $name;
return $this;
}
/**
* @param Cookie $cookie
* @return $this
*/
public function setCookie(Cookie $cookie)
{
$this->cookie = $cookie;
return $this;
}
/**
* @return bool
*/
public function loginTokenWasInvalid()
{
return $this->lastLoginTokenWasInvalid;
}
/**
* @return Cookie
*/
public function getCookie()
{
return $this->cookie;
}
/**
* @param $state
* @return Authenticator
*/
public function setCleanStoredTokensOnInvalidResult($state)
{
$this->cleanStoredTokensOnInvalidResult = $state;
return $this;
}
/**
* @return bool
*/
public function getCleanStoredTokensOnInvalidResult()
{
return $this->cleanStoredTokensOnInvalidResult;
}
/**
* Create a pseudo-random token.
*
* The token is pseudo-random. If you need better security, read from /dev/urandom
*/
protected function createToken()
{
return bin2hex(random_bytes(32));
}
/**
* @return array
*/
protected function getCookieValues()
{
// Cookie was not sent with incoming request
if (empty($_COOKIE[$this->cookieName])) {
return array();
}
$cookieValues = explode("|", $_COOKIE[$this->cookieName], 3);
if (count($cookieValues) < 3) {
return array();
}
return $cookieValues;
}
/**
* Return how many seconds in the future that the cookie will expire
* @return int
*/
public function getExpireTime()
{
return $this->expireTime;
}
/**
* @param int $expireTime How many seconds in the future the cookie will expire
*
* Default is 604800 (1 week)
*
* @return Authenticator
*/
public function setExpireTime($expireTime)
{
$this->expireTime = $expireTime;
return $this;
}
/**
*
* @return string
*/
public function getSalt()
{
return $this->salt;
}
/**
* The salt is additional information that is added to the tokens to make
* them more unqiue and secure. The salt is not stored in the cookie and
* should not saved in the storage.
*
* For example, to bind a token to an IP address use $_SERVER['REMOTE_ADDR'].
* To bind a token to the browser (user agent), use $_SERVER['HTTP_USER_AGENT].
* You could also use a long random string that is uniqe to your application.
* @param string $salt
*/
public function setSalt($salt)
{
$this->salt = $salt;
}
}