| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- <?php
- // src/Security/KeycloakAuthenticator.php
- namespace App\Security;
- use App\Entity\User;
- use App\Entity\Gamemaster;
- use Doctrine\ORM\EntityManagerInterface;
- use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
- use League\OAuth2\Client\Provider\ResourceOwnerInterface;
- use Symfony\Component\HttpFoundation\Request;
- use Symfony\Component\HttpFoundation\Response;
- use Symfony\Component\HttpFoundation\RedirectResponse;
- use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
- use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
- use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
- use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
- use Symfony\Component\Security\Core\Exception\AuthenticationException;
- use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
- use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
- use Symfony\Component\String\Slugger\AsciiSlugger;
- class KeycloakAuthenticator extends AbstractAuthenticator
- {
- public function __construct(
- private ClientRegistry $clientRegistry,
- private EntityManagerInterface $em,
- private UserPasswordHasherInterface $hasher,
- private UrlGeneratorInterface $urlGenerator
- ) {}
- public function supports(Request $request): ?bool
- {
- return $request->attributes->get('_route') === 'app_login_keycloak_connect_check';
- }
- public function authenticate(Request $request): SelfValidatingPassport
- {
-
- $client = $this->clientRegistry->getClient('keycloak');
- $accessToken = $client->getAccessToken();
- $keycloakUser = $client->fetchUserFromToken($accessToken);
- $data = $keycloakUser->toArray();
- if ($_ENV['KEYCLOAK_DEBUG'] == 1) {
- dump($data);
- }
- $email = $data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_EMAIL']] ?? null;
- return new SelfValidatingPassport(
- new UserBadge($email, function($email) use ($data) {
- $user = $this->em->getRepository(User::class)->findOneBy(['email' => $email]);
- if (!$user) {
- $user = new User();
- $user->setEmail($email);
- $user->setFirstName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_FIRSTNAME']] ?? '');
- $user->setLastName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_LASTNAME']] ?? '');
- $user->setPhone($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_PHONE']] ?? '');
- $user->setRoles(['ROLE_USER']);
- $user->setIsVerified(true);
- $user->setPassword(
- $this->hasher->hashPassword($user, bin2hex(random_bytes(10)))
- );
- $this->em->persist($user);
- } else {
- // Il vient de KC, donc, l'email est fiabilisé
- $user->setIsVerified(true);
- // Mise à jour du numéro de téléphone s'il est renseigné dans KC
- $user->setPhone($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_PHONE']] ?? $user->getPhone());
- $user->setFirstName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_FIRSTNAME']] ?? $user->getFirstName());
- $user->setLastName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_LASTNAME']] ?? $user->getLastName());
- }
-
- // Mise à jour des rôle et du profil GM
- if (in_array($_ENV['KEYCLOAK_ADMIN_GROUP'], $data['groups'])) {
- $user->setRoles(['ROLE_ADMIN']);
- } elseif (in_array($_ENV['KEYCLOAK_MANAGER_GROUP'], $data['groups'])) {
- $user->setRoles(['ROLE_MANAGER']);
- } elseif (in_array($_ENV['KEYCLOAK_STAFF_GROUP'], $data['groups'])) {
- $user->setRoles(['ROLE_STAFF']);
- }
-
- if (in_array($_ENV['KEYCLOAK_GAMEMASTER_GROUP'], $data['groups'])) {
- if (!$user->getLinkToGamemaster()) {
- // Créer un profil MJ
- $gamemaster = new Gamemaster();
- $gamemaster->setFirstName($user->getFirstName());
- $gamemaster->setLastName($user->getLastName());
- $gamemaster->setPreferedName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_NICKNAME']]);
- $slugger = new AsciiSlugger('fr_FR');
- $slug = $slugger->slug(strtolower($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_NICKNAME']]));
- $gamemaster->setSlug($slug);
- $gamemaster->setEmail($user->getEmail());
- $phone = $user->getPhone();
- if ($phone) { $gamemaster->setPhone($phone); }
- $gamemaster->setLinkToUser($user);
- $this->em->persist($gamemaster);
- } else {
- // Mettre à jour le profil MJ
- $gamemaster = $user->getLinkToGamemaster();
- $gamemaster->setFirstName($user->getFirstName());
- $gamemaster->setLastName($user->getLastName());
- $gamemaster->setPreferedName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_NICKNAME']]);
- $slugger = new AsciiSlugger('fr_FR');
- $slug = $slugger->slug(strtolower($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_NICKNAME']]));
- $gamemaster->setSlug($slug);
- $gamemaster->setEmail($user->getEmail());
- $phone = $user->getPhone();
- if ($phone) { $gamemaster->setPhone($phone); }
- }
- }
- $this->em->flush();
- return $user;
- })
- );
- }
- public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
- {
- return new RedirectResponse($this->urlGenerator->generate('app_main'));
- }
- public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
- {
- return new RedirectResponse($this->urlGenerator->generate('app_login'));
- }
- }
|