Comment faire un EventSubscriber

Par Devdeb22, il y a 6 ans


Bonjour les amis,

Je viens vers vous je butte sur un problème depuis maintenant plus de 3 jours.

J'essaye de comprendre comment fonctionne les Events dans symfony pour pouvoir l'utiliser avec Google Authentificator et je vous avouerai que je ne comprend pas encore grand choses.

Finalement après 3 jours d'efforts, je me suis décidé à prendre l'exemple que j'ai trouvé sur le web et a tanter de le modifier.

Problème quoi que je fasse, ça ne fonctionne.

Ce que je veux

Je souhaite que lorsque je me connecte à mon application, tous se passe comme il le faut.
Mais quand je demande l'url lié à la la route admin, Google Autentificator me demande de m'authentifier seulement et seulement si j'ai le rôle SUPER_ADMIN si je n'ai pas le role SUPER_ADMIN ça me renvoie une erreur 403

Ce que j'obtien

Actuellement, que je sois, SUPER_ADMIN ou USER à la connexion google me demande m'authentifier. De plus cela même si je n'ai pas demandé l'url lié à la route admin

Voici mon code pour le Subscriber

class TwoFactorAuthenticationSubscriber implements EventSubscriberInterface { const ROLE_2FA_SUCCEED = "2FA_SUCCEED"; const FIREWALL_NAME = "main"; const ROUTE_FOR_2FA = "two-factor"; /** * @var TokenStorageInterface */ private $tokenStorage; /** * @var RouterInterface */ private $router; /** * TwoFactorAuthenticationSubscriber constructor. * @param TokenStorageInterface $tokenStorage * @param RouterInterface $router */ public function __construct(TokenStorageInterface $tokenStorage, RouterInterface $router) { $this->tokenStorage = $tokenStorage; $this->router = $router; } public function onKernelRequest(GetResponseEvent $event) { if (!$event->isMasterRequest()) { return; } if (in_array($event->getRequest()->attributes->get('_route'), ["admin", self::ROUTE_FOR_2FA])) { return; } if (($currentToken = $this->tokenStorage->getToken()) && $currentToken instanceof PostAuthenticationGuardToken) { if ($currentToken->getProviderKey() === self::FIREWALL_NAME) { if (!$this->hasRole($currentToken, self::ROLE_2FA_SUCCEED)) { $response = new RedirectResponse($this->router->generate(self::ROUTE_FOR_2FA)); $event->setResponse($response); } } } } public static function getSubscribedEvents() { return [ KernelEvents::REQUEST => ['onKernelRequest', -10], ]; } private function hasRole(TokenInterface $token, string $role): bool { foreach ($token->getRoles() as $userRole) { if ($userRole->getRole() === $role) { return true; } } return false; } }

Et voici mon code sur controller

class TwoFactorAuthenticationController extends AbstractController { /** * @Route("/two-factor", name="two-factor") * @param Request $request * @param TokenStorageInterface $tokenStorage * @param SessionInterface $session * @param EntityManagerInterface $entityManager * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response * @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException */ public function twoFactorAction(Request $request, TokenStorageInterface $tokenStorage, SessionInterface $session, EntityManagerInterface $entityManager) { $form = $this->createForm(GoogleAuthenticatorType::class); $form->handleRequest($request); $google2fa = new Google2FA(); $svg = null; // Ici je met la condition de vérification du rôle de l'utilisateur $userCurrent = $this->getUser(); /** @var User $user */ $user = $this->getUser(); if (!$user->getGoogleAuthenticatorSecret()) { if ($session->get('2fa_secret')) { $secret = $session->get('2fa_secret'); } else { $secret = $google2fa->generateSecretKey(); $request->getSession()->set('2fa_secret', $secret); } $svg = $this->generateSvgForUser($google2fa, $user, $secret); } else { $secret = $user->getGoogleAuthenticatorSecret(); } if ($form->isSubmitted() && $form->isValid()) { $code = $form->getData()["code"]; $codeIsValid = $google2fa->verifyKey($secret, $code, 4); if ($codeIsValid) { if (!$user->getGoogleAuthenticatorSecret()) { $user->setGoogleAuthenticatorSecret($secret); $entityManager->persist($user); $entityManager->flush(); } $this->addRoleTwoFA($tokenStorage, $session); return $this->redirectToRoute("admin"); } $this->addFlash("error", "Invalid verification code"); } return $this->render("security/two-factor.html.twig", [ "svg" => $svg, "form" => $form->createView(), ]); } private function generateSvgForUser(Google2FA $google2FA, User $user, string $secret): string { $g2faUrl = $google2FA->getQRCodeUrl( "Uwandzani.com", $user->getUsername(), $secret ); $writer = new Writer( new ImageRenderer( new RendererStyle(400), new SvgImageBackEnd() // can also user new ImagickImageBackEnd() in order to generate png ) ); return $writer->writeString($g2faUrl); } private function addRoleTwoFA(TokenStorageInterface $tokenStorage, SessionInterface $session): void { /** @var PostAuthenticationGuardToken $currentToken */ $currentToken = $tokenStorage->getToken(); $roles = array_merge($currentToken->getRoles(), [TwoFactorAuthenticationSubscriber::ROLE_2FA_SUCCEED]); $newToken = new PostAuthenticationGuardToken($currentToken->getUser(), $currentToken->getProviderKey(), $roles); $tokenStorage->setToken($newToken); $session->set('_security_' . $currentToken->getProviderKey(), serialize($newToken)); } }

Aucune réponse