/src/Psecio/Gatekeeper/Session/RememberMe.php
https://github.com/psecio/gatekeeper · PHP · 266 lines · 133 code · 31 blank · 102 comment · 17 complexity · c9d7722a53dfb447df415736d1991a2c MD5 · raw file
- <?php
- namespace Psecio\Gatekeeper\Session;
- class RememberMe
- {
- /**
- * Token name
- * @var string
- */
- private $tokenName = 'gktoken';
- /**
- * Default expiration time
- * @var string
- */
- private $expireInterval = '+14 days';
- /**
- * Data (cookie) for use in token evaluation
- * @var array
- */
- private $data = array();
- /**
- * User instance to check against
- * @var \Psecio\Gatekeeper\UserModel
- */
- private $user;
- /**
- * Datasource for use in making find//save requests
- * @var \Psecio\Gatekeeper\DataSource
- */
- private $datasource;
- /**
- * Init the object and set up the datasource, data and possibly a user
- *
- * @param \Psecio\Gatekeeper\DataSource $datasource Data source to use for operations
- * @param array $data Data to use in evaluation
- * @param \Psecio\Gatekeeper\UserModel|null $user User model instance [optional]
- */
- public function __construct(\Psecio\Gatekeeper\DataSource $datasource, array $data, \Psecio\Gatekeeper\UserModel $user = null)
- {
- $this->datasource = $datasource;
- if (!empty($data)) {
- $this->data = $data;
- }
- if ($user !== null) {
- $this->user = $user;
- }
- if (isset($this->data['interval'])) {
- $this->expireInterval = $this->data['interval'];
- }
- }
- /**
- * Get the current data for the evaluation
- */
- public function getData()
- {
- return $this->data;
- }
- /**
- * Get the current user for evaluation
- */
- public function getUser()
- {
- return $this->user;
- }
- /**
- * Get the current expiration interval
- */
- public function getExpireInterval()
- {
- return $this->expireInterval;
- }
- /**
- * Setup the "remember me" session and cookies
- *
- * @param \Psecio\Gatekeeper\UserModel|null $user User model instance [optional]
- * @return boolean Success/fail of setting up the session/cookies
- */
- public function setup(\Psecio\Gatekeeper\UserModel $user = null)
- {
- $user = ($user === null) ? $this->user : $user;
- $userToken = $this->getUserToken($user);
- if ($userToken->id !== null || $this->isExpired($userToken)) {
- return false;
- }
- $token = $this->generateToken();
- $tokenModel = $this->saveToken($token, $user);
- if ($tokenModel === false) {
- return false;
- }
- $this->setCookies($tokenModel, $token);
- return true;
- }
- /**
- * Verify the token if it exists
- * Removes the old token and sets up a new one if valid
- *
- * @param \Psecio\Gatekeeper\AuthTokenModel $token Token model instance
- * @return boolean Pass/fail result of the validation
- */
- public function verify(\Psecio\Gatekeeper\AuthTokenModel $token = null)
- {
- if (!isset($this->data[$this->tokenName])) {
- return false;
- }
- if ($token === null) {
- $tokenParts = explode(':', $this->data[$this->tokenName]);
- $token = $this->getById($tokenParts[0]);
- }
- if ($token === false) {
- return false;
- }
- $user = $token->user;
- $userToken = $token->token;
- // Remove the token (a new one will be made later)
- $this->datasource->delete($token);
- if (\Psecio\Gatekeeper\Gatekeeper::hash_equals($this->data[$this->tokenName], $token->id.':'.hash('sha256', $userToken)) === false) {
- return false;
- }
- $this->setup($user);
- return $user;
- }
- /**
- * Get the token information searching on given token string
- *
- * @param string $tokenValue Token string for search
- * @return boolean|\Psecio\Gatekeeper\AuthTokenModel Instance if no query errors
- */
- public function getByToken($tokenValue)
- {
- $token = new \Psecio\Gatekeeper\AuthTokenModel($this->datasource);
- $result = $this->datasource->find($token, array('token' => $tokenValue));
- return $result;
- }
- /**
- * Get a token by its unique ID
- *
- * @param integer $tokenId Token ID
- * @return boolean|\Psecio\Gatekeeper\AuthTokenModel instance
- */
- public function getById($tokenId)
- {
- $token = new \Psecio\Gatekeeper\AuthTokenModel($this->datasource);
- $result = $this->datasource->find($token, array('id' => $tokenId));
- return $result;
- }
- /**
- * Get the token by user ID
- * Also performs evaluation to check if token is expired, returns false if so
- *
- * @param \Psecio\Gatekeeper\UserModel $user User model instance
- * @return boolean|\Psecio\Gatekeeper\AuthTokenModel instance
- */
- public function getUserToken(\Psecio\Gatekeeper\UserModel $user)
- {
- $tokenModel = new \Psecio\Gatekeeper\AuthTokenModel($this->datasource);
- return $this->datasource->find($tokenModel, array('userId' => $user->id));
- }
- /**
- * Check to see if the token has expired
- *
- * @param \Psecio\Gatekeeper\AuthTokenModel $token Token model instance
- * @param boolean $delete Delete/don't delete the token if expired [optional]
- * @return boolean Token expired/not expired
- */
- public function isExpired(\Psecio\Gatekeeper\AuthTokenModel $token, $delete = true)
- {
- if ($token->expires !== null && new \Datetime() > new \DateTime($token->expires)) {
- if ($delete === true) {
- $this->deleteToken($token->token);
- }
- return true;
- }
- return false;
- }
- /**
- * Save the new token to the data source
- *
- * @param string $token Token string
- * @param \Psecio\Gatekeeper\UserModel $user User model instance
- * @return boolean|\Psecio\Gatekeeper\AuthTokenModel Success/fail of token creation or AuthTokenModel instance
- */
- public function saveToken($token, \Psecio\Gatekeeper\UserModel $user)
- {
- $expires = new \DateTime($this->expireInterval);
- $tokenModel = new \Psecio\Gatekeeper\AuthTokenModel($this->datasource, array(
- 'token' => $token,
- 'userId' => $user->id,
- 'expires' => $expires->format('Y-m-d H:i:s')
- ));
- $result = $this->datasource->save($tokenModel);
- return ($result === false) ? false : $tokenModel;
- }
- /**
- * Delete the token by token string
- *
- * @param string $token Token hash string
- * @return boolean Success/fail of token record deletion
- */
- public function deleteToken($token)
- {
- $tokenModel = new \Psecio\Gatekeeper\AuthTokenModel($this->datasource);
- $token = $this->datasource->find($tokenModel, array('token' => $token));
- if ($token !== false) {
- return $this->datasource->delete($token);
- }
- return false;
- }
- /**
- * Generate the token value
- *
- * @return string Token hash
- */
- public function generateToken()
- {
- $factory = new \RandomLib\Factory;
- $generator = $factory->getMediumStrengthGenerator();
- return base64_encode($generator->generate(24));
- }
- /**
- * Set the cookies with the main and auth tokens
- *
- * @param \Psecio\Gatekeeper\AuthTokenModel $tokenModel Auth token model instance
- * @param string $token Token hash
- * @param boolean $https Enable/disable HTTPS setting on cookies [optional]
- * @param string $domain Domain value to set cookies on
- */
- public function setCookies(\Psecio\Gatekeeper\AuthTokenModel $tokenModel, $token, $https = false, $domain = null)
- {
- if ($domain === null && isset($_SERVER['HTTP_HOST'])) {
- $domain = ($_SERVER['HTTP_HOST'] != 'localhost') ? $_SERVER['HTTP_HOST'] : false;
- }
- $tokenValue = $tokenModel->id.':'.hash('sha256', $token);
- $expires = new \DateTime($this->expireInterval);
- return setcookie($this->tokenName, $tokenValue, $expires->format('U'), '/', $domain, $https, true);
- }
- }