vendor/pimcore/pimcore/lib/Tool/Authentication.php line 70

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Enterprise License (PEL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  * @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  * @license    http://www.pimcore.org/license     GPLv3 and PEL
  13.  */
  14. namespace Pimcore\Tool;
  15. use Defuse\Crypto\Crypto;
  16. use Defuse\Crypto\Exception\CryptoException;
  17. use Pimcore\Logger;
  18. use Pimcore\Model\User;
  19. use Pimcore\Tool;
  20. use Symfony\Component\HttpFoundation\Request;
  21. class Authentication
  22. {
  23.     /**
  24.      * @param string $username
  25.      * @param string $password
  26.      *
  27.      * @return null|User
  28.      */
  29.     public static function authenticatePlaintext($username$password)
  30.     {
  31.         /** @var User $user */
  32.         $user User::getByName($username);
  33.         // user needs to be active, needs a password and an ID (do not allow system user to login, ...)
  34.         if (self::isValidUser($user)) {
  35.             if (self::verifyPassword($user$password)) {
  36.                 $user->setLastLoginDate(); //set user current login date
  37.                 return $user;
  38.             }
  39.         }
  40.         return null;
  41.     }
  42.     /**
  43.      * @static
  44.      *
  45.      * @param Request $request
  46.      *
  47.      * @return User|null
  48.      */
  49.     public static function authenticateSession(Request $request null)
  50.     {
  51.         if (null === $request) {
  52.             $request = \Pimcore::getContainer()->get('request_stack')->getCurrentRequest();
  53.             if (null === $request) {
  54.                 return null;
  55.             }
  56.         }
  57.         if (!Session::requestHasSessionId($requesttrue)) {
  58.             // if no session cookie / ID no authentication possible, we don't need to start a session
  59.             return null;
  60.         }
  61.         $session Session::getReadOnly();
  62.         $user $session->get('user');
  63.         if ($user instanceof User) {
  64.             // renew user
  65.             $user User::getById($user->getId());
  66.             if (self::isValidUser($user)) {
  67.                 return $user;
  68.             }
  69.         }
  70.         return null;
  71.     }
  72.     /**
  73.      * @static
  74.      *
  75.      * @throws \Exception
  76.      *
  77.      * @return User
  78.      */
  79.     public static function authenticateHttpBasic()
  80.     {
  81.         // we're using Sabre\HTTP for basic auth
  82.         $request = \Sabre\HTTP\Sapi::getRequest();
  83.         $response = new \Sabre\HTTP\Response();
  84.         $auth = new \Sabre\HTTP\Auth\Basic(Tool::getHostname(), $request$response);
  85.         $result $auth->getCredentials();
  86.         if (is_array($result)) {
  87.             list($username$password) = $result;
  88.             $user self::authenticatePlaintext($username$password);
  89.             if ($user) {
  90.                 return $user;
  91.             }
  92.         }
  93.         $auth->requireLogin();
  94.         $response->setBody('Authentication required');
  95.         Logger::error('Authentication Basic (WebDAV) required');
  96.         \Sabre\HTTP\Sapi::sendResponse($response);
  97.         die();
  98.     }
  99.     /**
  100.      * @param string $token
  101.      * @param bool $adminRequired
  102.      *
  103.      * @return null|User
  104.      */
  105.     public static function authenticateToken($token$adminRequired false)
  106.     {
  107.         $username null;
  108.         $timestamp null;
  109.         try {
  110.             $decrypted self::tokenDecrypt($token);
  111.             list($timestamp$username) = $decrypted;
  112.         } catch (CryptoException $e) {
  113.             return null;
  114.         }
  115.         $user User::getByName($username);
  116.         if (self::isValidUser($user)) {
  117.             if ($adminRequired and !$user->isAdmin()) {
  118.                 return null;
  119.             }
  120.             $timeZone date_default_timezone_get();
  121.             date_default_timezone_set('UTC');
  122.             if ($timestamp time() or $timestamp < (time() - (60 60 24))) {
  123.                 return null;
  124.             }
  125.             date_default_timezone_set($timeZone);
  126.             return $user;
  127.         }
  128.         return null;
  129.     }
  130.     /**
  131.      * @param User $user
  132.      * @param string $password
  133.      *
  134.      * @return bool
  135.      */
  136.     public static function verifyPassword($user$password)
  137.     {
  138.         $password self::preparePlainTextPassword($user->getName(), $password);
  139.         if ($user->getPassword()) { // do not allow logins for users without a password
  140.             if (password_verify($password$user->getPassword())) {
  141.                 if (password_needs_rehash($user->getPassword(), PASSWORD_DEFAULT)) {
  142.                     $user->setPassword(self::getPasswordHash($user->getName(), $password));
  143.                     $user->save();
  144.                 }
  145.                 return true;
  146.             }
  147.         }
  148.         return false;
  149.     }
  150.     /**
  151.      * @param User|null $user
  152.      *
  153.      * @return bool
  154.      */
  155.     public static function isValidUser($user)
  156.     {
  157.         if ($user instanceof User && $user->isActive() && $user->getId() && $user->getPassword()) {
  158.             return true;
  159.         }
  160.         return false;
  161.     }
  162.     /**
  163.      * @param string $username
  164.      * @param string $plainTextPassword
  165.      *
  166.      * @return bool|false|string
  167.      *
  168.      * @throws \Exception
  169.      */
  170.     public static function getPasswordHash($username$plainTextPassword)
  171.     {
  172.         $hash password_hash(self::preparePlainTextPassword($username$plainTextPassword), PASSWORD_DEFAULT);
  173.         if (!$hash) {
  174.             throw new \Exception('Unable to create password hash for user: ' $username);
  175.         }
  176.         return $hash;
  177.     }
  178.     /**
  179.      * @param string $username
  180.      * @param string $plainTextPassword
  181.      *
  182.      * @return string
  183.      */
  184.     public static function preparePlainTextPassword($username$plainTextPassword)
  185.     {
  186.         // plaintext password is prepared as digest A1 hash, this is to be backward compatible because this was
  187.         // the former hashing algorithm in pimcore (< version 2.1.1)
  188.         return md5($username ':pimcore:' $plainTextPassword);
  189.     }
  190.     /**
  191.      * @param string $username
  192.      *
  193.      * @return string
  194.      */
  195.     public static function generateToken($username)
  196.     {
  197.         $secret = \Pimcore::getContainer()->getParameter('secret');
  198.         $data time() - '|' $username;
  199.         $token Crypto::encryptWithPassword($data$secret);
  200.         return $token;
  201.     }
  202.     /**
  203.      * @param string $token
  204.      *
  205.      * @return array
  206.      */
  207.     public static function tokenDecrypt($token)
  208.     {
  209.         $secret = \Pimcore::getContainer()->getParameter('secret');
  210.         $decrypted Crypto::decryptWithPassword($token$secret);
  211.         return explode('|'$decrypted);
  212.     }
  213. }