Categories
Tags
API Audit Auditor Bundle Authentication Bulma Cache Castor ChatGPT Development Développement Web DevOps Docker Documentation Facebook FrankenPHP Fullstack GitHub Google JavaScript Linux Linux Mint MacBook Pro macOS Makefile OAuth2 OpenAI Optimization Performance PHP PHPUnit Pop!_OS Process Management Profile README Setup SQL Svelte Symfony Symfony Lock Technology Tutorial Verrouillage Web Development Workflow
341 words
2 minutes
Authentication with Google in Symfony 6
In this article, we will see how to log into a site using your Google or Facebook credentials, etc. (see the full list here). We will assume this method will be exclusive (no password).
Creating the User Entity
Here is what the User entity looks like:
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\Table(name: '`user`')]
class User implements UserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 180, unique: true)]
private $email;
#[ORM\Column(type: 'json')]
private $roles = [];
#[ORM\Column(type: 'string', length: 255)]
private $googleId;
#[ORM\Column(type: 'text', nullable: true)]
private $avatar;
#[ORM\Column(type: 'string', length: 255)]
private $hostedDomain;
}Installing Dependencies
Add the required dependencies:
composer require knpuniversity/oauth2-client-bundle
composer require league/oauth2-googleConfiguration
Add the following configuration to config/packages/knpu_oauth2_client.yaml:
knpu_oauth2_client:
clients:
google:
type: google
client_id: '%env(resolve:GOOGLE_CLIENT_ID)%'
client_secret: '%env(resolve:GOOGLE_CLIENT_SECRET)%'
redirect_route: connect_google_check
redirect_params: {}Then, add the GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET variables to your .env file.
Creating the Google Controller
Create a controller to manage the connection:
<?php
namespace App\Controller;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class GoogleController extends AbstractController
{
#[Route('/connect/google', name: 'connect_google')]
public function connectAction(ClientRegistry $clientRegistry)
{
return $clientRegistry->getClient('google')->redirect([], []);
}
#[Route('/connect/google/check', name: 'connect_google_check')]
public function connectCheckAction(Request $request)
{
// Empty method for guard authentication
}
}Authentication with OAuth2Authenticator
Create an authentication class:
<?php
namespace App\Security;
use App\Entity\User;
use League\OAuth2\Client\Provider\GoogleUser;
use Doctrine\ORM\EntityManagerInterface;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use KnpU\OAuth2ClientBundle\Security\Authenticator\OAuth2Authenticator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
class GoogleAuthenticator extends OAuth2Authenticator
{
private ClientRegistry $clientRegistry;
private EntityManagerInterface $entityManager;
private RouterInterface $router;
public function __construct(ClientRegistry $clientRegistry, EntityManagerInterface $entityManager, RouterInterface $router)
{
$this->clientRegistry = $clientRegistry;
$this->entityManager = $entityManager;
$this->router = $router;
}
public function supports(Request $request): ?bool
{
return $request->attributes->get('_route') === 'connect_google_check';
}
public function authenticate(Request $request): Passport
{
$client = $this->clientRegistry->getClient('google');
$accessToken = $this->fetchAccessToken($client);
return new SelfValidatingPassport(
new UserBadge($accessToken->getToken(), function () use ($accessToken, $client) {
$googleUser = $client->fetchUserFromToken($accessToken);
$email = $googleUser->getEmail();
$existingUser = $this->entityManager->getRepository(User::class)->findOneBy(['googleId' => $googleUser->getId()]);
if (!$existingUser) {
$existingUser = new User();
$existingUser->setEmail($email);
$existingUser->setGoogleId($googleUser->getId());
$existingUser->setHostedDomain($googleUser->getHostedDomain());
$this->entityManager->persist($existingUser);
}
$existingUser->setAvatar($googleUser->getAvatar());
$this->entityManager->flush();
return $existingUser;
})
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
return new Response('Connection successful.', Response::HTTP_OK);
}
}Conclusion
That’s it! You can now access /connect/google to log in via Google and be authenticated in your application.
