src/Listener/JWTListener.php line 50

Open in your IDE?
  1. <?php
  2. namespace App\Listener;
  3. use App\Entity\User;
  4. use App\Manager\UserRightsManagerInterface;
  5. use App\Model\Permissions\AreaRights;
  6. use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent;
  7. use Psr\Log\LoggerInterface;
  8. use RuntimeException;
  9. use Symfony\Component\Security\Core\User\UserInterface;
  10. class JWTListener
  11. {
  12.     /**
  13.      * @var UserRightsManagerInterface
  14.      */
  15.     protected $rightsManager;
  16.     /**
  17.      * @var LoggerInterface
  18.      */
  19.     protected $logger;
  20.     /**
  21.      * JWTListener constructor.
  22.      *
  23.      * @param UserRightsManagerInterface $rightsManager
  24.      * @param LoggerInterface            $logger
  25.      */
  26.     public function __construct(
  27.         UserRightsManagerInterface $rightsManager,
  28.         LoggerInterface $logger
  29.     ) {
  30.         $this->rightsManager $rightsManager;
  31.         $this->logger        $logger;
  32.     }
  33.     public const TOKEN_TTL 3600// one hour
  34.     /**
  35.      * Hook for when JWT is created: let's customize the payload.
  36.      *
  37.      * @see https://github.com/lexik/LexikJWTAuthenticationBundle/blob/master/Resources/doc/2-data-customization.md
  38.      *
  39.      * @param JWTCreatedEvent $event
  40.      *
  41.      * @return void
  42.      */
  43.     public function onJWTCreated(JWTCreatedEvent $event)
  44.     {
  45.         $eventUser $event->getUser();
  46.         $payload   $event->getData();
  47.         // Authentication
  48.         $payload['id']           = $eventUser->getId(); //uidNumber
  49.         $payload['email']        = $eventUser->getEmail(); //uid
  50.         $payload['firstName']    = $eventUser->getFirstName(); //givenName
  51.         $payload['lastName']     = $eventUser->getLastName(); //sn
  52.         $payload['ldapUuid']     = $eventUser->getLdapUuid(); //ldapUuid
  53.         $payload['phone']        = $eventUser->getPhone(); //telephonenumber
  54.         $payload['mobilePhone']  = $eventUser->getMobilePhone(); // mobile
  55.         $payload['organisation'] = $eventUser->getOrganisation(); // o
  56.         // Authorizations
  57.         $payload['roles'] = array_merge($this->getRoles($eventUser), $eventUser->getRoles());
  58.         $areas            $this->getAreas($eventUser);
  59.         $payload['areas'] = $areas->toJson();
  60.         $event->setData($payload);
  61.     }
  62.     /**
  63.      * Defines set of role for User.
  64.      *
  65.      * @param UserInterface $user
  66.      *
  67.      * @return array
  68.      *
  69.      * @throws RuntimeException When user has an illegal type
  70.      */
  71.     protected function getRoles(UserInterface $user): array
  72.     {
  73.         switch ($user->getType()) {
  74.             case User::TYPE_SAML:
  75.             case User::TYPE_PUBLIK_SSO_POLE_MANAGER:
  76.                 return $this->getSamlRights($user);
  77.             case User::TYPE_PUBLIK_SSO:
  78.                 // Roles set by entrypoint, no need to recalculate them.
  79.                 return $user->getRoles();
  80.             default:
  81.                 $this->logger->critical(
  82.                     '[JWTCreated] User with type {type} is not eligible to role computation!',
  83.                     [
  84.                         'type'  => $user->getType(),
  85.                         'email' => $user->getEmail(),
  86.                     ]
  87.                 );
  88.                 throw new RuntimeException('Invalid user type');
  89.         }
  90.     }
  91.     /**
  92.      * Defines set of areas for User.
  93.      *
  94.      * @param UserInterface $user
  95.      *
  96.      * @return AreaRights
  97.      *
  98.      * @throws RuntimeException When user has an illegal type
  99.      */
  100.     protected function getAreas(UserInterface $user): AreaRights
  101.     {
  102.         switch ($user->getType()) {
  103.             case User::TYPE_SAML:
  104.             case User::TYPE_PUBLIK_SSO_POLE_MANAGER:
  105.                 return $this->getSamlAreas($user);
  106.             case User::TYPE_PUBLIK_SSO:
  107.                 // Areas set by entrypoint, no need to recalculate them.
  108.                 return $user->getAreaRights();
  109.             default:
  110.                 $this->logger->critical(
  111.                     '[JWTCreated] User with type {type} is not eligible to area computation!',
  112.                     [
  113.                         'type'  => $user->getType(),
  114.                         'email' => $user->getEmail(),
  115.                     ]
  116.                 );
  117.                 throw new RuntimeException('Invalid user type');
  118.         }
  119.     }
  120.     /**
  121.      * Calls Heimdall to compute user roles
  122.      *
  123.      * @param User $user
  124.      *
  125.      * @return array
  126.      */
  127.     protected function getSamlRights(User $user): array
  128.     {
  129.         $roles $this->rightsManager->getUserRoles($user);
  130.         $this->logger->info(
  131.             '[JWTCreated] Computing rights for SAML user {email}. Granted: {roles}',
  132.             [
  133.                 'email' => $user->getEmail(),
  134.                 'roles' => json_encode($roles),
  135.             ]
  136.         );
  137.         return $roles;
  138.     }
  139.     /**
  140.      * Calls Heimdall to compute user areas
  141.      *
  142.      * @param UserInterface $user
  143.      *
  144.      * @return AreaRights
  145.      */
  146.     protected function getSamlAreas(UserInterface $user): AreaRights
  147.     {
  148.         $areas $this->rightsManager->getAreaRights($user);
  149.         $this->logger->info(
  150.             '[JWTCreated] Computing rights for SAML user {email}. Granted: {roles}',
  151.             [
  152.                 'email' => $user->getEmail(),
  153.                 'areas' => $areas->toJson(),
  154.             ]
  155.         );
  156.         return $areas;
  157.     }
  158. }