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

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 Commercial License (PCL)
  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 PCL
  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.      * @param Request|null $request
  44.      *
  45.      * @return User|null
  46.      */
  47.     public static function authenticateSession(Request $request null)
  48.     {
  49.         if (null === $request) {
  50.             $request \Pimcore::getContainer()->get('request_stack')->getCurrentRequest();
  51.             if (null === $request) {
  52.                 return null;
  53.             }
  54.         }
  55.         if (!Session::requestHasSessionId($requesttrue)) {
  56.             // if no session cookie / ID no authentication possible, we don't need to start a session
  57.             return null;
  58.         }
  59.         $session Session::getReadOnly();
  60.         $user $session->get('user');
  61.         if ($user instanceof User) {
  62.             // renew user
  63.             $user User::getById($user->getId());
  64.             if (self::isValidUser($user)) {
  65.                 return $user;
  66.             }
  67.         }
  68.         return null;
  69.     }
  70.     /**
  71.      * @throws \Exception
  72.      *
  73.      * @return User
  74.      */
  75.     public static function authenticateHttpBasic()
  76.     {
  77.         // we're using Sabre\HTTP for basic auth
  78.         $request \Sabre\HTTP\Sapi::getRequest();
  79.         $response = new \Sabre\HTTP\Response();
  80.         $auth = new \Sabre\HTTP\Auth\Basic(Tool::getHostname(), $request$response);
  81.         $result $auth->getCredentials();
  82.         if (is_array($result)) {
  83.             list($username$password) = $result;
  84.             $user self::authenticatePlaintext($username$password);
  85.             if ($user) {
  86.                 return $user;
  87.             }
  88.         }
  89.         $auth->requireLogin();
  90.         $response->setBody('Authentication required');
  91.         Logger::error('Authentication Basic (WebDAV) required');
  92.         \Sabre\HTTP\Sapi::sendResponse($response);
  93.         die();
  94.     }
  95.     /**
  96.      * @param string $token
  97.      * @param bool $adminRequired
  98.      *
  99.      * @return null|User
  100.      */
  101.     public static function authenticateToken($token$adminRequired false)
  102.     {
  103.         $username null;
  104.         $timestamp null;
  105.         try {
  106.             $decrypted self::tokenDecrypt($token);
  107.             list($timestamp$username) = $decrypted;
  108.         } catch (CryptoException $e) {
  109.             return null;
  110.         }
  111.         $user User::getByName($username);
  112.         if (self::isValidUser($user)) {
  113.             if ($adminRequired && !$user->isAdmin()) {
  114.                 return null;
  115.             }
  116.             $timeZone date_default_timezone_get();
  117.             date_default_timezone_set('UTC');
  118.             if ($timestamp time() || $timestamp < (time() - (60 60 24))) {
  119.                 return null;
  120.             }
  121.             date_default_timezone_set($timeZone);
  122.             return $user;
  123.         }
  124.         return null;
  125.     }
  126.     /**
  127.      * @param User $user
  128.      * @param string $password
  129.      *
  130.      * @return bool
  131.      */
  132.     public static function verifyPassword($user$password)
  133.     {
  134.         $password self::preparePlainTextPassword($user->getName(), $password);
  135.         if ($user->getPassword()) { // do not allow logins for users without a password
  136.             if (password_verify($password$user->getPassword())) {
  137.                 if (password_needs_rehash($user->getPassword(), PASSWORD_DEFAULT)) {
  138.                     $user->setPassword(self::getPasswordHash($user->getName(), $password));
  139.                     $user->save();
  140.                 }
  141.                 return true;
  142.             }
  143.         }
  144.         return false;
  145.     }
  146.     /**
  147.      * @param User|null $user
  148.      *
  149.      * @return bool
  150.      */
  151.     public static function isValidUser($user)
  152.     {
  153.         if ($user instanceof User && $user->isActive() && $user->getId() && $user->getPassword()) {
  154.             return true;
  155.         }
  156.         return false;
  157.     }
  158.     /**
  159.      * @internal
  160.      *
  161.      * @param string $username
  162.      * @param string $plainTextPassword
  163.      *
  164.      * @return string
  165.      *
  166.      * @throws \Exception
  167.      */
  168.     public static function getPasswordHash($username$plainTextPassword)
  169.     {
  170.         $hash password_hash(self::preparePlainTextPassword($username$plainTextPassword), PASSWORD_DEFAULT);
  171.         if (!$hash) {
  172.             throw new \Exception('Unable to create password hash for user: ' $username);
  173.         }
  174.         return $hash;
  175.     }
  176.     /**
  177.      * @param string $username
  178.      * @param string $plainTextPassword
  179.      *
  180.      * @return string
  181.      */
  182.     private static function preparePlainTextPassword($username$plainTextPassword)
  183.     {
  184.         // plaintext password is prepared as digest A1 hash, this is to be backward compatible because this was
  185.         // the former hashing algorithm in pimcore (< version 2.1.1)
  186.         return md5($username ':pimcore:' $plainTextPassword);
  187.     }
  188.     /**
  189.      * @internal
  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.     private static function tokenDecrypt($token)
  208.     {
  209.         $secret \Pimcore::getContainer()->getParameter('secret');
  210.         $decrypted Crypto::decryptWithPassword($token$secret);
  211.         return explode('|'$decrypted);
  212.     }
  213. }