src/Security/GoogleAuthenticator.php line 41

  1. <?php
  2. namespace App\Security;
  3. use App\Entity\User// your user entity
  4. use App\Service\UserUpkeep;
  5. use Doctrine\ORM\EntityManagerInterface;
  6. use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
  7. use KnpU\OAuth2ClientBundle\Security\Authenticator\OAuth2Authenticator;
  8. use League\OAuth2\Client\Provider\GoogleUser;
  9. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  10. use Symfony\Component\HttpFoundation\RedirectResponse;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\Response;
  13. use Symfony\Component\PasswordHasher\Hasher\MessageDigestPasswordHasher;
  14. use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory;
  15. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher;
  16. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  17. use Symfony\Component\Routing\RouterInterface;
  18. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  19. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  20. use Symfony\Component\Security\Core\User\InMemoryUser;
  21. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
  22. use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
  23. use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
  24. class GoogleAuthenticator extends OAuth2Authenticator
  25. {
  26.     private $clientRegistry;
  27.     private $entityManager;
  28.     private $router;
  29.     private $userUpkeep;
  30.     private $userPasswordHasherInterface;
  31.     public function __construct(ClientRegistry $clientRegistryEntityManagerInterface $entityManagerRouterInterface $routerUserUpkeep $userUpkeepUserPasswordHasherInterface $userPasswordHasherInterfaceParameterBagInterface $params)
  32.     {
  33.         $this->clientRegistry $clientRegistry;
  34.         $this->entityManager $entityManager;
  35.         $this->router $router;
  36.         $this->userUpkeep $userUpkeep;
  37.         $this->userPasswordHasherInterface $userPasswordHasherInterface;
  38.         $this->params $params;
  39.     }
  40.     public function supports(Request $request): ?bool
  41.     {
  42.         // continue ONLY if the current ROUTE matches the check ROUTE
  43.         return $request->attributes->get('_route') === 'connect_google_check';
  44.     }
  45.     public function authenticate(Request $request): Passport
  46.     {
  47.         $client $this->clientRegistry->getClient('google_main');
  48.         $accessToken $this->fetchAccessToken($client);
  49.         return new SelfValidatingPassport(
  50.             new UserBadge($accessToken->getToken(), function() use ($accessToken$client) {
  51.                 /** @var GoogleUser $googleUser */
  52.                 $googleUser $client->fetchUserFromToken($accessToken);
  53.                 $email $googleUser->getEmail();
  54.                 // 1) have they logged in with Google before? Easy!
  55.                 $existingUser $this->entityManager->getRepository(User::class)->findOneBy(['googleId' => $googleUser->getId()]);
  56.                 if ($existingUser) {
  57.                     $this->_generateGameToken($existingUser$this->entityManager);
  58.                     return $existingUser;
  59.                 }
  60.                 // 2) do we have a matching user by email?
  61.                 $user $this->entityManager->getRepository(User::class)->findOneBy(['email' => $email]);
  62.                 if($user) {
  63.                     $user->setGoogleId($googleUser->getId());
  64.                     $this->_generateGameToken($user$this->entityManager);
  65.                 } else {
  66.                     // Create a new User
  67.                     $user = new User();
  68.                     $user->setEmail($email);
  69.                     $user->setGoogleId($googleUser->getId());
  70.                     $user->setPassword($this->userPasswordHasherInterface->hashPassword($user$this->_generateRandomString(10)));
  71.                     $this->entityManager->persist($user);
  72.                     $this->userUpkeep->addStartingEquipment($user);
  73.                     $this->userUpkeep->addTemplateStats($user);
  74.                     $this->userUpkeep->addUserGearSlots($user);
  75.                     $this->_generateGameToken($user$this->entityManager);
  76.                     $this->entityManager->flush();
  77.                 }
  78.                 return $user;
  79.             })
  80.         );
  81.     }
  82.     public function onAuthenticationSuccess(Request $requestTokenInterface $tokenstring $firewallName): ?Response
  83.     {
  84.         // change "app_homepage" to some route in your app
  85.         $targetUrl $this->router->generate('default', ['domain' => $this->params->get('app.domain')]);
  86.         return new RedirectResponse($targetUrl);
  87.         // or, on success, let the request continue to be handled by the controller
  88.         //return null;
  89.     }
  90.     public function onAuthenticationFailure(Request $requestAuthenticationException $exception): ?Response
  91.     {
  92.         $message strtr($exception->getMessageKey(), $exception->getMessageData());
  93.         return new Response($messageResponse::HTTP_FORBIDDEN);
  94.     }
  95.     private function _generateRandomString($length 10) {
  96.         $characters '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  97.         $charactersLength strlen($characters);
  98.         $randomString '';
  99.         for ($i 0$i $length$i++) {
  100.             $randomString .= $characters[rand(0$charactersLength 1)];
  101.         }
  102.         return $randomString;
  103.     }
  104.     private function _generateGameToken(User $userEntityManagerInterface $entityManager) {
  105.         // Set a new game token on login
  106.         $gameToken hash('sha256'$this->_generateRandomString() . $user->getEmail());
  107.         $user->setGameToken($gameToken);
  108.         $this->entityManager->persist($user);
  109.         $this->entityManager->flush();
  110.     }
  111. //    private function _generatePassword(User $user, string $password, UserPasswordHasherInterface $userPasswordHasherInterface) {
  112. //        return $userPasswordHasherInterface->hashPassword(
  113. //                $user,
  114. //                $password
  115. //        );
  116. //    }
  117. }