src/Controller/LinkedinController.php line 24

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\User;
  4. use App\Security\AppAuthenticator;
  5. use GuzzleHttp\Client;
  6. use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
  7. use League\OAuth2\Client\Provider\LinkedIn;
  8. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  9. use Symfony\Component\HttpFoundation\Response;
  10. use Symfony\Component\Routing\Annotation\Route;
  11. use Doctrine\ORM\EntityManagerInterface;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
  14. use Symfony\Contracts\HttpClient\HttpClientInterface;
  15. class LinkedinController extends AbstractController
  16. {
  17.     private LinkedIn $login_provider;
  18.     private LinkedIn $register_provider;
  19.     public function __construct()
  20.     {
  21.         $this->login_provider = new LinkedIn([
  22.             'clientId' => $_ENV['LINKEDIN_ID'],
  23.             'clientSecret' => $_ENV['LINKEDIN_SECRET'],
  24.             'redirectUri' => $_ENV['LINKEDIN_CALLBACK']
  25.         ]);
  26.         $this->register_provider = new LinkedIn([
  27.             'clientId' => $_ENV['LINKEDIN_ID'],
  28.             'clientSecret' => $_ENV['LINKEDIN_SECRET'],
  29.             'redirectUri' => $_ENV['LINKEDIN_CALLBACK_REGISTER']
  30.         ]);
  31.     }
  32.     /**
  33.      * @Route("/linkedin-login", name="linkedin_login")
  34.      */
  35.     public function linkedinLogin(): Response
  36.     {
  37.         $options = [
  38.             'scope' => ['openid''profile''email'// array or string
  39.         ];
  40.         $helper_url $this->login_provider->getAuthorizationUrl($options);
  41.         return $this->redirect($helper_url);
  42.     }
  43.     /**
  44.      * @Route("/linkedin-save/register", name="linkedin_save")
  45.      */
  46.     public function linkedinRegister(): Response
  47.     {
  48.         $options = [
  49.             'scope' => ['openid''profile''email'// array or string
  50.         ];
  51.         $helper_url $this->register_provider->getAuthorizationUrl($options);
  52.         return $this->redirect($helper_url);
  53.     }
  54.     /**
  55.      * @Route("/linkedin-callback", name="linkedin_callback")
  56.      * @throws IdentityProviderException
  57.      */
  58.     public function linkedinCallBack(
  59.         EntityManagerInterface     $manager,
  60.         UserAuthenticatorInterface $userAuthenticator,
  61.         AppAuthenticator           $authenticator,
  62.         Request                    $request,
  63.         HttpClientInterface $client
  64.     ): Response {
  65.         //Récupérer le token
  66.         $token $this->login_provider->getAccessToken('authorization_code', [
  67.             'code' => $_GET['code']
  68.         ]);
  69.         try {
  70.             //Récupérer les informations de l'utilisateur
  71.             // Options de la requête
  72.             $options = [
  73.                 'headers' => [
  74.                     'Authorization' => 'Bearer ' $token// Ajout du jeton Bearer dans l'en-tête
  75.                     'Content-Type' => 'application/json'// Spécification du type de contenu
  76.                 ],
  77.             ];
  78.             // Exemple de requête GET avec les options spécifiées
  79.             $response $client->request('GET'"https://api.linkedin.com/v2/userinfo"array_merge($options, [
  80.                 'timeout' => 5,
  81.             ]))->getContent();
  82.             $user json_decode($response);
  83.             $email $user->email;
  84.             //Vérifier si l'utilisateur existe dans la base des données
  85.             $user_exist $manager->getRepository(User::class)->findOneBy(
  86.                 [
  87.                     'email' => $email
  88.                 ]
  89.             );
  90.             if ($user_exist) {
  91.                 if (!empty($user->picture)) {
  92.                     $urlPhoto $this->downloadAndSaveAvatar($user->picture);
  93.                     $user_exist->setPhoto($urlPhoto);
  94.                     if ($user_exist->isFreelance()) {
  95.                         $user_exist->getUniqueProfile()->setPhoto($urlPhoto);
  96.                     }
  97.                 }
  98.                 return $userAuthenticator->authenticateUser(
  99.                     $user_exist,
  100.                     $authenticator,
  101.                     $request
  102.                 );
  103.             } else {
  104.                 $this->addFlash('error-google'"Votre compte linkedIn n'est pas associé à cette application.\n Veuillez vous inscrire! ");
  105.                 return $this->redirectToRoute('login');
  106.             }
  107.         } catch (\Throwable $th) {
  108.             //throw $th;
  109.             return new Response($th->getMessage());
  110.         }
  111.     }
  112.     /**
  113.      * @Route("/linkedin-callback-register", name="linkedin_callback_register")
  114.      *
  115.      * @throws IdentityProviderException
  116.      */
  117.     public function linkedinCallBackRegister(
  118.         EntityManagerInterface     $manager,
  119.         UserAuthenticatorInterface $userAuthenticator,
  120.         AppAuthenticator           $authenticator,
  121.         Request                    $request,
  122.         HttpClientInterface $client
  123.     ): Response {
  124.         //Récupérer le token
  125.         $token $this->register_provider->getAccessToken('authorization_code', [
  126.             'code' => $_GET['code']
  127.         ]);
  128.         try {
  129.             //Récupérer les informations de l'utilisateur
  130.             $options = [
  131.                 'headers' => [
  132.                     'Authorization' => 'Bearer ' $token// Ajout du jeton Bearer dans l'en-tête
  133.                     'Content-Type' => 'application/json'// Spécification du type de contenu
  134.                 ],
  135.             ];
  136.             $response $client->request('GET'"https://api.linkedin.com/v2/userinfo"array_merge($options, [
  137.                 'timeout' => 5,
  138.             ]))->getContent();
  139.             $linkedinUser json_decode($response);
  140.             $email $linkedinUser->email;
  141.             //Vérifier si l'utilisateur existe dans la base des données
  142.             $user_exist $manager->getRepository(User::class)->findOneBy(
  143.                 [
  144.                     'email' => $email
  145.                 ]
  146.             );
  147.             if ($user_exist) {
  148.                 return $userAuthenticator->authenticateUser(
  149.                     $user_exist,
  150.                     $authenticator,
  151.                     $request
  152.                 );
  153.             } else {
  154.                 $user = new User();
  155.                 $user->setCreatedAt(new \DateTime());
  156.                 $user->setRoles(['ROLE_FREELANCE']);
  157.                 $user->setType('freelance');
  158.                 $user->setPhone('');
  159.                 // ADDED INFO
  160.                 $user->setEmail($linkedinUser->email);
  161.                 $user->setPassword('__LINKEDIN__AUTH__');
  162.                 $user->setLastname($linkedinUser->family_name);
  163.                 $user->setFirstname($linkedinUser->given_name);
  164.                 $user->setGoogleSubId($linkedinUser->sub);
  165.                 $user->setIsVerified(true);
  166.                 if (!empty($linkedinUser->picture)) {
  167.                     $urlPhoto $this->downloadAndSaveAvatar($linkedinUser->picture);
  168.                     // dd($urlPhoto);
  169.                     $user->setPhoto($urlPhoto);
  170.                     $user->getUniqueProfile()->setPhoto($urlPhoto);
  171.                 }
  172.                 $manager->persist($user);
  173.                 $manager->flush();
  174.                 $user->setPassword($user->getId() . '__LINKEDIN__AUTH__');
  175.                 $manager->persist($user);
  176.                 $manager->flush();
  177.                 return $userAuthenticator->authenticateUser(
  178.                     $user,
  179.                     $authenticator,
  180.                     $request
  181.                 );
  182.             }
  183.         } catch (\Throwable $th) {
  184.             //throw $th;
  185.             return new Response($th->getMessage());
  186.         }
  187.     }
  188.     private function downloadAndSaveAvatar(string $imageUrl): ?string
  189.     {
  190.         $client = new Client();
  191.         $publicDir $this->getParameter('avatar_directory') . '/';
  192.         try {
  193.             // Faire une requête GET pour télécharger l'image avec un timeout
  194.             $response $client->get($imageUrl, [
  195.                 'timeout' => 5,
  196.                 'connect_timeout' => 2,
  197.             ]);
  198.             $contentType $response->getHeader('Content-Type')[0];
  199.             // Vérifier si c'est une image
  200.             if (strpos($contentType'image/') !== 0) {
  201.                 throw new \Exception("Ce n'est pas une image valide.");
  202.             }
  203.             // Déterminer l'extension de l'image
  204.             $extension explode('/'$contentType)[1]; // par exemple "jpeg" ou "png"
  205.             // Générer un nom unique pour l'image
  206.             $uniqueFileName 'avatar-' uniqid() . '.' $extension;
  207.             // Chemin complet pour enregistrer l'image
  208.             $filePath $publicDir $uniqueFileName;
  209.             // Enregistrer l'image localement
  210.             file_put_contents($filePath$response->getBody());
  211.             return $uniqueFileName// Retourner le nom du fichier enregistré
  212.         } catch (\Exception $e) {
  213.             // Gérer l'erreur
  214.             return null;
  215.         }
  216.     }
  217. }