<?php
namespace App\Security;
use App\Kernel;
use App\Entity\User; // your user entity
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use League\OAuth2\Client\Provider\GoogleUser;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use KnpU\OAuth2ClientBundle\Security\Authenticator\OAuth2Authenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
class GoogleAuthenticator extends OAuth2Authenticator
{
private $clientRegistry;
private $entityManager;
private $router;
private $kernel;
public function __construct(ClientRegistry $clientRegistry, EntityManagerInterface $entityManager, RouterInterface $router, Kernel $kernel)
{
$this->clientRegistry = $clientRegistry;
$this->entityManager = $entityManager;
$this->router = $router;
$this->kernel = $kernel;
}
public function supports(Request $request): ?bool
{
// continue ONLY if the current ROUTE matches the check ROUTE
return $request->attributes->get('_route') === 'connect_google_check';
}
public function authenticate(Request $request): Passport
{
$client = $this->clientRegistry->getClient('google_main');
$accessToken = $this->fetchAccessToken($client);
return new SelfValidatingPassport(
new UserBadge($accessToken->getToken(), function() use ($accessToken, $client) {
/** @var GoogleUser $googleUser */
$googleUser = $client->fetchUserFromToken($accessToken);
$email = $googleUser->getEmail();
// Если в базе нет пользователя с таким email, то сохраняем его
/** @var User $user */
$user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $email]);
if(!$user->getId()) {
$user = new User();
}
if ($googleUser->getId() != $user->getGoogleId()) {
$user->setGoogleId($googleUser->getId());
}
if (!$user->getName()) {
$user->setName($googleUser->getFirstName());
}
if (!$user->getSurname()) {
$user->setSurname($googleUser->getLastName());
}
$this->entityManager->persist($user);
$this->entityManager->flush();
// Если в базе еще нет фото, а в фейсбук есть фото, то сохраняем его
// $user_pic = $this->kernel->getProjectDir()."/public/pic/user/".$user->getId().".jpg";
// if ($googleUser->getAvatar() && !file_exists($user_pic)) {
// copy($googleUser->getAvatar(), $user_pic);
// }
return $user;
})
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
$targetUrl = $this->router->generate('user');
return new RedirectResponse($targetUrl);
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
$message = strtr($exception->getMessageKey(), $exception->getMessageData());
return new Response($message, Response::HTTP_FORBIDDEN);
}
}