src/Controller/GoogleController.php line 45

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\ActiviteUser;
  4. use App\Entity\User;
  5. use App\Security\AppAuthenticator;
  6. use GuzzleHttp\Client;
  7. use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
  8. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  9. use Symfony\Component\HttpFoundation\Response;
  10. use Symfony\Component\Routing\Annotation\Route;
  11. use League\OAuth2\Client\Provider\Google;
  12. use Doctrine\ORM\EntityManagerInterface;
  13. use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
  14. use Symfony\Component\HttpFoundation\JsonResponse;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
  17. class GoogleController extends AbstractController
  18. {
  19.     private Google $login_provider;
  20.     private Google $register_provider;
  21.     public function __construct()
  22.     {
  23.         $this->login_provider = new Google([
  24.             'clientId' => $_ENV['GGL_ID'],
  25.             'clientSecret' => $_ENV['GGL_SECRET'],
  26.             'redirectUri' => $_ENV['GGL_CALLBACK'],
  27.             'graphApiVersion' => 'v18.0',
  28.         ]);
  29.         $this->register_provider = new Google([
  30.             'clientId' => $_ENV['GGL_ID'],
  31.             'clientSecret' => $_ENV['GGL_SECRET'],
  32.             'redirectUri' => $_ENV['GGL_CALLBACK_REGISTER'],
  33.             'graphApiVersion' => 'v18.0',
  34.         ]);
  35.     }
  36.     /**
  37.      * @Route("/ggl-login", name="ggl_login")
  38.      */
  39.     public function gglLogin(): Response
  40.     {
  41.         $helper_url $this->login_provider->getAuthorizationUrl();
  42.         return $this->redirect($helper_url);
  43.     }
  44.     /**
  45.      * @Route("/ggl-save/register", name="ggl_save")
  46.      */
  47.     public function gglRegister(): Response
  48.     {
  49.         $helper_url $this->register_provider->getAuthorizationUrl();
  50.         return $this->redirect($helper_url);
  51.     }
  52.     /**
  53.      * @Route("/ggl-callback", name="ggl_callback")
  54.      * @throws IdentityProviderException
  55.      */
  56.     public function gglCallBack(
  57.         EntityManagerInterface     $manager,
  58.         UserAuthenticatorInterface $userAuthenticator,
  59.         AppAuthenticator           $authenticator,
  60.         Request                    $request,
  61.         JWTTokenManagerInterface   $jwtManager
  62.     ): Response {
  63.         $token $this->login_provider->getAccessToken('authorization_code', [
  64.             'code' => $_GET['code']
  65.         ]);
  66.         try {
  67.             $user $this->login_provider->getResourceOwner($token)->toArray();
  68.             $email $user['email'];
  69.             $user_exist $manager->getRepository(User::class)->findOneBy(['email' => $email]);
  70.             if ($user_exist) {
  71.                 if (!empty($user['picture'])) {
  72.                     $urlPhoto $this->downloadAndSaveAvatar($user['picture']);
  73.                     $user_exist->setPhoto($urlPhoto);
  74.                     if ($user_exist->isFreelance()) {
  75.                         $user_exist->getUniqueProfile()->setPhoto($urlPhoto);
  76.                     }
  77.                 }
  78.                 return $userAuthenticator->authenticateUser($user_exist$authenticator$request);
  79.             } else {
  80.                 $this->addFlash('error-google'"Votre compte google n'est pas associé à cette application.\n Veuillez vous inscrire!");
  81.                 return $this->redirectToRoute('login');
  82.             }
  83.         } catch (\Throwable $th) {
  84.             $this->addFlash('error-google'"Une erreur est survenue lors de la connexion Google. Veuillez réessayer.");
  85.             return $this->redirectToRoute('login');
  86.         }
  87.     }
  88.     // Route pour afficher la page de redirection
  89.     /**
  90.      * @Route("/redirect-to-exp", name="redirect_to_exp")
  91.      */
  92.     public function redirectToExp(Request $request): Response
  93.     {
  94.         $clientId $request->query->get('client_id');
  95.         // Désactivé: aucune tentative d'ouverture d'application mobile
  96.         return new Response(
  97.             '<html>
  98.             <head>
  99.                 <meta charset="UTF-8">
  100.                 <title>Redirection</title>
  101.             </head>
  102.             <body>
  103.                 <p>Aucune redirection vers une application mobile. Vous pouvez continuer sur le site.</p>
  104.             </body>
  105.         </html>'
  106.         );
  107.     }
  108.     /**
  109.      * @Route("/ggl-callback-register", name="ggl_callback_register")
  110.      * @throws IdentityProviderException
  111.      */
  112.     public function gglCallBackRegister(
  113.         EntityManagerInterface     $manager,
  114.         UserAuthenticatorInterface $userAuthenticator,
  115.         AppAuthenticator           $authenticator,
  116.         Request                    $request,
  117.         JWTTokenManagerInterface   $jwtManager
  118.     ): Response {
  119.         $token $this->register_provider->getAccessToken('authorization_code', [
  120.             'code' => $_GET['code']
  121.         ]);
  122.         try {
  123.             $googleUser $this->register_provider->getResourceOwner($token)->toArray();
  124.             $email $googleUser['email'];
  125.             $user_exist $manager->getRepository(User::class)->findOneBy(['email' => $email]);
  126.             if ($user_exist) {
  127.                 if (!empty($googleUser['picture'])) {
  128.                     $urlPhoto $this->downloadAndSaveAvatar($googleUser['picture']);
  129.                     $user_exist->setPhoto($urlPhoto);
  130.                     if ($user_exist->isFreelance()) {
  131.                         $user_exist->getUniqueProfile()->setPhoto($urlPhoto);
  132.                     }
  133.                 }
  134.                 return $userAuthenticator->authenticateUser($user_exist$authenticator$request);
  135.             } else {
  136.                 $user = new User();
  137.                 $user->setCreatedAt(new \DateTime());
  138.                 $user->setRoles(['ROLE_FREELANCE']);
  139.                 $user->setType('freelance');
  140.                 $user->setPhone('');
  141.                 $user->setEmail($googleUser['email']);
  142.                 $user->setPassword('__GOOGLE__AUTH__');
  143.                 $user->setLastname($googleUser['family_name'] ?? " ");
  144.                 $user->setFirstname($googleUser['given_name'] ?? " ");
  145.                 $user->setGoogleSubId($googleUser['sub']);
  146.                 $user->setIsVerified(true);
  147.                 if (!empty($googleUser['picture'])) {
  148.                     $urlPhoto $this->downloadAndSaveAvatar($googleUser['picture']);
  149.                     $user->setPhoto($urlPhoto);
  150.                     $user->getUniqueProfile()->setPhoto($urlPhoto);
  151.                 }
  152.                 $manager->persist($user);
  153.                 $manager->flush();
  154.                 $user->setPassword($user->getId() . '__GOOGLE__AUTH__');
  155.                 $manager->persist($user);
  156.                 $manager->flush();
  157.                 return $userAuthenticator->authenticateUser($user$authenticator$request);
  158.             }
  159.         } catch (\Throwable $th) {
  160.             $this->addFlash('error-google'"Une erreur est survenue lors de l'inscription Google. Veuillez réessayer.");
  161.             return $this->redirectToRoute('login');
  162.         }
  163.     }
  164.     /**
  165.      * @Route("/api/mobile/google", name="mobile_google_login", methods={"POST"})
  166.      */
  167.     public function googleLogin(Request $requestEntityManagerInterface $managerJWTTokenManagerInterface $jwtManager): JsonResponse
  168.     {
  169.         // Récupérer le token envoyé depuis l'application mobile
  170.         $data json_decode($request->getContent(), true);
  171.         $idToken $data['id_token'] ?? null;
  172.         if (!$idToken) {
  173.             return new JsonResponse(['error' => 'Token manquant'], 400);
  174.         }
  175.         // Vérifier le token via Google
  176.         // $client = new Google_Client(['client_id' => $_ENV['GGL_ID']]); // ID client de ton app
  177.         // $payload = $client->verifyIdToken($idToken);
  178.         $client = new \GuzzleHttp\Client();
  179.         $response $client->get('https://oauth2.googleapis.com/tokeninfo', [
  180.             'query' => ['id_token' => $idToken],
  181.         ]);
  182.         if ($response->getStatusCode() !== 200) {
  183.             throw new \Exception('Token invalide');
  184.         }
  185.         $payload json_decode($response->getBody(), true);
  186.         // Vérifie que l'audience (aud) correspond à ton client_id
  187.         if ($payload['aud'] !== $_ENV['GGL_ID']) {
  188.             throw new \Exception('Token émis pour un autre client_id');
  189.         }
  190.         if (!$payload) {
  191.             return new JsonResponse(['error' => 'Token invalide'], 401);
  192.         }
  193.         $email $payload['email'];
  194.         $sub $payload['sub']; // Le sub (ID unique) est important pour identifier l'utilisateur
  195.         // Chercher l'utilisateur dans la base
  196.         $user $manager->getRepository(User::class)->findOneBy(['email' => $email]);
  197.         if (!$user) {
  198.             // Si l'utilisateur n'existe pas, le créer
  199.             $user = new User();
  200.             $user->setEmail($email);
  201.             $user->setFirstname($payload['given_name'] ?? ""); // Optionnel
  202.             $user->setLastname($payload['family_name'] ?? ""); // Optionnel
  203.             $user->setGoogleSubId($sub); // ID unique de Google pour la liaison
  204.             $user->setPassword('__GOOGLE__AUTH__'); // Utilise un mot de passe fictif pour Google
  205.             $manager->persist($user);
  206.             $manager->flush();
  207.         }
  208.         // Générer le JWT avec LexikJWT
  209.         $token $jwtManager->create($user); // Création du JWT pour l'utilisateur
  210.         return new JsonResponse(['token' => $token]);
  211.     }
  212.     private function downloadAndSaveAvatar(string $imageUrl): ?string
  213.     {
  214.         $client = new Client();
  215.         $publicDir $this->getParameter('avatar_directory') . '/';
  216.         try {
  217.             // Faire une requête GET pour télécharger l'image
  218.             $response $client->get($imageUrl);
  219.             $contentType $response->getHeader('Content-Type')[0];
  220.             // Vérifier si c'est une image
  221.             if (strpos($contentType'image/') !== 0) {
  222.                 throw new \Exception("Ce n'est pas une image valide.");
  223.             }
  224.             // Déterminer l'extension de l'image
  225.             $extension explode('/'$contentType)[1]; // par exemple "jpeg" ou "png"
  226.             // Générer un nom unique pour l'image
  227.             $uniqueFileName 'avatar-' uniqid() . '.' $extension;
  228.             // Chemin complet pour enregistrer l'image
  229.             $filePath $publicDir $uniqueFileName;
  230.             // Enregistrer l'image localement
  231.             file_put_contents($filePath$response->getBody());
  232.             return $uniqueFileName// Retourner le nom du fichier enregistré
  233.         } catch (\Exception $e) {
  234.             // Gérer l'erreur
  235.             return null;
  236.         }
  237.     }
  238. }