vendor/elements/azure-auth-bundle/src/Controller/AuthController.php line 37

Open in your IDE?
  1. <?php
  2. namespace Elements\Bundle\AzureAuthBundle\Controller;
  3. use Elements\Bundle\AzureAuthBundle\DependencyInjection\ElementsAzureAuthExtension;
  4. use Elements\Bundle\AzureAuthBundle\Service\RestrictionService;
  5. use Pimcore\Model\User;
  6. use Pimcore\File;
  7. use Pimcore\Model\WebsiteSetting;
  8. use Pimcore\Tool;
  9. use Psr\Log\LoggerAwareInterface;
  10. use Psr\Log\LoggerAwareTrait;
  11. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Exception;
  14. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
  15. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  16. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  17. use TheNetworg\OAuth2\Client\Provider\Azure as AzureProvider;
  18. use TheNetworg\OAuth2\Client\Token\AccessToken as AzureAccessToken;
  19. class AuthController extends AbstractController implements LoggerAwareInterface
  20. {
  21.     use LoggerAwareTrait;
  22.     public function endpointAction(Request $requestRestrictionService $restrictionService) {
  23.         if (!$restrictionService->checkIpAddresses($request->getClientIp())) {
  24.             throw new AccessDeniedException();
  25.         }
  26.         $session $request->getSession();
  27.         /** @var SessionBagInterface $sessionBag */
  28.         $sessionBag $session->getBag('azure_auth');
  29.         $provider = new AzureProvider([
  30.             'clientId'                  => $this->getParameter('elements.azure_auth.clientId'),
  31.             'clientSecret'              => $this->getParameter('elements.azure_auth.clientSecret'),
  32.             'redirectUri'               => $this->getRedirectUrl($request),
  33.             'tenant'                    => $this->getParameter('elements.azure_auth.tenant'),
  34.             'defaultEndPointVersion'    => '2.0'
  35.         ]);
  36.         // Set to use v2 API, skip the line or set the value to Azure::ENDPOINT_VERSION_1_0 if willing to use v1 API
  37.         $provider->defaultEndPointVersion \TheNetworg\OAuth2\Client\Provider\Azure::ENDPOINT_VERSION_2_0;
  38.         $baseGraphUri $provider->getRootMicrosoftGraphUri(null);
  39.         $provider->scope 'openid ' $baseGraphUri '/User.Read';
  40.         if (isset($_GET['code']) && $sessionBag->has('OAuth2.state') && isset($_GET['state'])) {
  41.             if ($_GET['state'] == $sessionBag->get('OAuth2.state')) {
  42.                 $sessionBag->remove('OAuth2.state');
  43.                 // Try to get an access token (using the authorization code grant)
  44.                 /** @var AzureAccessToken $token */
  45.                 $token $provider->getAccessToken('authorization_code', [
  46.                     'scope' => $provider->scope,
  47.                     'code' => $_GET['code'],
  48.                     'response_type' => 'code id_token',
  49.                 ]);
  50.                 try {
  51.                     $data $this->consolidateData($provider$token);
  52.                     $email $data['mail'];
  53.                     $isDomainPermitted false;
  54.                     if (isset($email)) {
  55.                         foreach ($this->getParameter(ElementsAzureAuthExtension::PERMITTED_DOMAINS) as $domain) {
  56.                             if (str_ends_with($email$domain)) {
  57.                                 $isDomainPermitted true;
  58.                                 break;
  59.                             }
  60.                         }
  61.                     }
  62.                     if(isset($email) && $isDomainPermitted) {
  63.                         $sessionBag->set('azureUser'$data);
  64.                         $sessionBag->set('azureAccessToken'$token);
  65.                         if ($this->getParameter(ElementsAzureAuthExtension::CHECK_USER_LOGIN_PERMISSION) == true) {
  66.                             if (WebsiteSetting::getByName('AzureLoginPreselect') instanceof WebsiteSetting){
  67.                                 $allowArray explode(',', (WebsiteSetting::getByName('AzureLoginPreselect')->getData() ?? ''));
  68.                                 if (!in_array($data['userPrincipalName'], $allowArray)) {
  69.                                     $sessionBag->clear();
  70.                                     return $this->redirect("/admin");
  71.                                 }
  72.                             }
  73.                         }
  74.                         $user $this->loadUser($data,$provider$token);
  75.                         if($user instanceof User && $user->getId() && $user->isActive()) {
  76.                             Tool\Session::useSession(function (AttributeBagInterface $adminSession) use ($user) {
  77.                                 $adminSession->set('user'$user);
  78.                                 Tool\Session::regenerateId();
  79.                             });
  80.                             return $this->redirect("/admin");
  81.                         } else {
  82.                             $message sprintf("User with email %s doesn't exist ... Sorry!"$email);
  83.                             $this->logger->error($message);
  84.                             throw new \Exception($message);
  85.                         }
  86.                     } else {
  87.                         $message sprintf("%s it seems that your email domain is currently not permitted ... Sorry!"$email);
  88.                         $this->logger->error($message);
  89.                         throw new \Exception($message);
  90.                     }
  91.                 } catch (Exception $e) {
  92.                     // Failed to get user details
  93.                     //exit('Oh dear...');
  94.                     $this->logger->error($e->getMessage());
  95.                     throw $e;
  96.                 }
  97.             } else {
  98.                 $message 'Invalid state';
  99.                 $this->logger->error($message);
  100.                 echo $message;
  101.                 exit;
  102.             }
  103.         } else {
  104.             $authorizationUrl $provider->getAuthorizationUrl(['scope' => $provider->scope]);
  105.             $sessionBag->set('OAuth2.state'$provider->getState());
  106.             return $this->redirect($authorizationUrl);
  107.         }
  108.     }
  109.     /**
  110.      * @param User $user
  111.      * @param AzureProvider $provider
  112.      * @param AzureAccessToken $token
  113.      * @return void
  114.      */
  115.     private function updateUserImage(User $userAzureProvider $providerAzureAccessToken $token)
  116.     {
  117.         try{
  118.             $photo $provider->get($provider->getRootMicrosoftGraphUri($token) . '/v1.0/me/photo/$value'$token);
  119.             if($photo){
  120.                 $tmpFile PIMCORE_SYSTEM_TEMP_DIRECTORY '/azure-image-download-' $user->getId() . ".jpg";
  121.                 File::put($tmpFile$photo);
  122.                 $user->setImage($tmpFile);
  123.                 $user->save();
  124.                 unlink($tmpFile);
  125.             }
  126.         } catch (\Exception $e){
  127.             $this->logger->error($e->getMessage());
  128.         }
  129.     }
  130.     /**
  131.      * @param AzureProvider $provider
  132.      * @param AzureAccessToken $token
  133.      * @return array|mixed|string
  134.      */
  135.     private function consolidateData(AzureProvider $providerAzureAccessToken $token)
  136.     {
  137.         $data $provider->get($provider->getRootMicrosoftGraphUri($token) . '/v1.0/me'$token);
  138.         $additionalData $provider->get($provider->getRootMicrosoftGraphUri($token) . '/v1.0/users/' $data['id'] . '?$select=onPremisesSamAccountName'$token);
  139.         $data['userPrincipalName'] = strtolower($data['userPrincipalName']);
  140.         $data['mail'] = strtolower($data['mail']);
  141.         $data['onPremisesSamAccountName'] = $additionalData['onPremisesSamAccountName'];
  142.         return $data;
  143.     }
  144.     /**
  145.      * @param array $data
  146.      * @return User
  147.      * @throws Exception
  148.      */
  149.     protected function loadUser(array $dataAzureProvider $providerAzureAccessToken $token)
  150.     {
  151.         $email $data['mail'] ?? $data['userPrincipalName'];
  152.         /** @var User $user */
  153.         $user User::getByName($email);
  154.         // rewrite user to email address
  155.         if (!$user) {
  156.             $user $this->rewriteEmail($data);
  157.         }
  158.         // check if user exists, if not create one
  159.         if (!$user) {
  160.             $user $this->createUser($data$provider$token);
  161.         }
  162.         // temp.
  163.         if (!$user->isAdmin() && $this->getParameter(ElementsAzureAuthExtension::CREATE_USER_AS_ADMIN) == true) {
  164.             $user->setAdmin(true);
  165.             $user->save();
  166.         }
  167.         if (!$user->isActive()) {
  168.             $user->setActive(true);
  169.         }
  170.         if(method_exists($user'setLastLogin')) {
  171.             $user->setLastLogin(time());
  172.         }
  173.         $user->save();
  174.         return $user;
  175.     }
  176.     /**
  177.      * @param array $data
  178.      * @param AzureProvider $provider
  179.      * @param AzureAccessToken $token
  180.      * @return User
  181.      * @throws Exception
  182.      */
  183.     protected function createUser(array $dataAzureProvider $providerAzureAccessToken $token)
  184.     {
  185.         $email $data['mail'] ?? $data['userPrincipalName'];
  186.         if (str_contains($email'@')) {
  187.             $domain explode('@'$email)[1]; // elements.at or any other company domain
  188.         } else {
  189.             $domain 'elements.at';
  190.         }
  191.         $folder User\Folder::getByName($domain);
  192.         if (!$folder) {
  193.             $folder = new User\Folder();
  194.             $folder->setName($domain);
  195.             $folder->setParentId(0);
  196.             $folder->save();
  197.         }
  198.         $user = new User;
  199.         $user->setParentId($folder->getId());
  200.         $user->setName($email);
  201.         $user->setActive(true);
  202.         if($isAdmin $this->getParameter(ElementsAzureAuthExtension::CREATE_USER_AS_ADMIN)) {
  203.             $user->setAdmin($isAdmin);
  204.         }
  205.         if($roleNames $this->getParameter(ElementsAzureAuthExtension::CREATE_USER_WITH_ROLES)) {
  206.             $rolesIds = [];
  207.             foreach ($roleNames as $roleName) {
  208.                 $role User\Role::getByName($roleName);
  209.                 if($role) {
  210.                     $rolesIds[] = $role->getId();
  211.                 }
  212.             }
  213.             $user->setRoles($rolesIds);
  214.         }
  215.         $user->setFirstname($data['givenName']);
  216.         $user->setLastname($data['surname']);
  217.         $user->setEmail($email);
  218.         $user->setPassword($data['id'] . microtime(true) . uniqid());
  219.         $user->save();
  220.         $this->updateUserImage($user$provider$token);
  221.         return $user;
  222.     }
  223.     /**
  224.      * @param array $data
  225.      * @return User|null
  226.      * @throws Exception
  227.      */
  228.     private function rewriteEmail(array $data)
  229.     {
  230.         if (!isset($data['onPremisesSamAccountName'])) {
  231.             return null;
  232.         }
  233.         // fetch user with old name
  234.         $user User::getByName($data['onPremisesSamAccountName']);
  235.         if($user){
  236.             // rewrite
  237.             $email $data['mail'] ?? $data['userPrincipalName'];
  238.             $user->setName($email);
  239.             $user->save();
  240.         }
  241.         return $user;
  242.     }
  243.     private function getRedirectUrl(Request $request)
  244.     {
  245.         $redirectUri 'https://' $request->getHttpHost() . $request->getPathInfo();
  246.         if(strpos($request->headers->get('x-original-host'), '.expose.eledevs.com') == true || strpos($request->headers->get('x-original-host'), '.expose.vdevs.at') == true) {
  247.             $redirectUri str_replace(':8080''''https://' $request->headers->get('x-original-host')) . $request->getPathInfo();
  248.         }
  249.         return $redirectUri;
  250.     }
  251. }