src/Controller/DefaultController.php line 32

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controller;
  4. use App\Entity\User;
  5. use App\Security\Authenticate;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use OneLogin\Saml2\Auth;
  8. use OneLogin\Saml2\Response as AuthResponse;
  9. use RuntimeException;
  10. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  11. use Symfony\Component\HttpFoundation\Response;
  12. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  13. use Symfony\Component\Routing\Annotation\Route;
  14. use Symfony\Contracts\Translation\TranslatorInterface;
  15. class DefaultController extends AbstractController
  16. {
  17.     public const URL_USERNAME_ATTRIBUTE 'http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname';
  18.     public const PATTERN_RESPONSE_SAML '%<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">(.+)@convictionsrh.com</saml%';
  19.     public function __construct(
  20.         private readonly EntityManagerInterface $em,
  21.         private readonly TranslatorInterface $translator,
  22.         private readonly UserPasswordHasherInterface $passwordHasher
  23.     ) {
  24.     }
  25.     #[Route('/'name'index')]
  26.     public function index(): Response
  27.     {
  28.         return $this->redirectToRoute('editor_index');
  29.     }
  30.     #[Route('/acs'name'acs'methods: ['GET''POST'])]
  31.     public function acs(Authenticate $authenticate): Response
  32.     {
  33.         $oneloginSettings $this->getParameter('nbgrp_onelogin_saml.onelogin_settings');
  34.         if (!\is_array($oneloginSettings)) {
  35.             throw new \UnexpectedValueException($this->translator->trans('onelogin.exception.arraySettings'));
  36.         }
  37.         $auth = new Auth($oneloginSettings['default']);
  38.         if (!isset($_POST['SAMLResponse'])) {
  39.             return new Response(
  40.                 $this->translator->trans('onelogin.exception.authFailed'),
  41.                 Response::HTTP_BAD_REQUEST
  42.             );
  43.         }
  44.         $response = new AuthResponse($auth->getSettings(), $_POST['SAMLResponse']);
  45.         $attr $response->getAttributes();
  46.         $username $attr[self::URL_USERNAME_ATTRIBUTE][0] ?? null;
  47.         $user $this->em->getRepository(User::class)->findOneBy(['email' => $username]);
  48.         if (null === $user && preg_match(self::PATTERN_RESPONSE_SAML$response->document->saveHTML(), $matches)) {
  49.             $username $matches[1];
  50.             $user $this->em->getRepository(User::class)->findOneBy(['email' => $username]);
  51.         }
  52.         $responseMessage null;
  53.         if (null !== $user) {
  54.             if ($user->isDeleted()) {
  55.                 $responseMessage $this->translator->trans('onelogin.userDeleted');
  56.             }
  57.         } else {
  58.             $user = new User();
  59.             $user->setEmail($username);
  60.             $user->setDeleted(false);
  61.             // Create PWD.
  62.             $plainPassword substr(
  63.                 str_shuffle(
  64.                     strtolower(
  65.                         sha1(
  66.                             rand() . time() . uniqid()
  67.                         )
  68.                     )
  69.                 ),
  70.                 0,
  71.                 16
  72.             );
  73.             $encodedPassword $this->passwordHasher->hashPassword($user$plainPassword);
  74.             $user->setPassword($encodedPassword);
  75.             $this->em->persist($user);
  76.             $this->em->flush();
  77.         }
  78.         if (null !== $responseMessage) {
  79.             return new Response($responseMessageResponse::HTTP_FORBIDDEN);
  80.         }
  81.         echo $this->translator->trans('onelogin.connected', ['%username%' => $username]);
  82.         $authenticate->login($user);
  83.         return $this->redirectToRoute('editor_index');
  84.     }
  85.     #[Route('/connect'name'connect'methods: ['GET''POST'])]
  86.     public function connect(): Response
  87.     {
  88.         $auth = new Auth();
  89.         $metadata $auth->getSettings()->getSPMetadata();
  90.         $response = new Response($metadata);
  91.         $response->headers->set('Content-Type''xml');
  92.         return $response;
  93.     }
  94.     // This will never be executed: Symfony will intercept this first and handle the logout automatically.
  95.     #[Route('/logout'name'logout')]
  96.     public function logout(): void
  97.     {
  98.         throw new RuntimeException('This should never be reached!');
  99.     }
  100. }