Documentation

🚀 Integrating Google Login into Symfony using Google Cloud Project

Last updated: June 8, 2025


1. 🤔 Why Use a Google Cloud Project for Google Login?

Your Google Cloud Project is essential because it:

  • Enables and manages the Google Identity (OAuth 2.0) API
  • Generates OAuth client credentials (Client ID, Secret)
  • Defines authorized redirect URIs
  • Manages billing, IAM roles, quotas, logs, and more

2. 🛠️ Prerequisites

  • PHP 8.4+
  • Symfony 7.2+ (or Symfony 5.4+)
  • Composer
  • A Google Cloud Project with OAuth enabled and a web app client created ✨

Set these in .env.local:

OAUTH_GOOGLE_CLIENT_ID=your-google-client-id
OAUTH_GOOGLE_CLIENT_SECRET=your-google-client-secret

3. 🔌 Integration Steps

3.1 Install Required Libraries

composer require knpuniversity/oauth2-client-bundle league/oauth2-google

3.2 Configure OAuth Client

In config/packages/knpu_oauth2_client.yaml:

knpu_oauth2_client:
  clients:
    google_main:
      type: google
      client_id: '%env(OAUTH_GOOGLE_CLIENT_ID)%'
      client_secret: '%env(OAUTH_GOOGLE_CLIENT_SECRET)%'
      redirect_route: connect_google_check
      access_type: offline
      redirect_params: []

3.3 Create Controller and Routes

// src/Controller/GoogleController.php
namespace App\Controller;

use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

class GoogleController extends AbstractController
{
    #[Route('/connect/google', name: 'connect_google_start')]
    public function connect(ClientRegistry $clientRegistry)
    {
        return $clientRegistry
            ->getClient('google_main')
            ->redirect(['email', 'profile'], ['prompt' => 'consent', 'access_type' => 'offline']);
    }

    #[Route('/connect/google/check', name: 'connect_google_check')]
    public function check()
    {
        // Handled by Symfony’s security system
    }
}

3.4 Build Custom Authenticator

// src/Security/GoogleAuthenticator.php
namespace App\Security;

use KnpU\OAuth2ClientBundle\Security\Authenticator\OAuth2Authenticator;
// imports...

class GoogleAuthenticator extends OAuth2Authenticator
{
    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_main');
        $accessToken = $this->fetchAccessToken($client);

        return new SelfValidatingPassport(new UserBadge($accessToken->getToken(), function($token) use ($client, $accessToken) {
            $googleUser = $client->fetchUserFromToken($accessToken);
            $email = $googleUser->getEmail();

            $user = $this->em->getRepository(User::class)->findOneBy(['email' => $email]);
            if (!$user) {
                $user = new User();
                $user->setEmail($email);
                $this->em->persist($user);
            }

            $user->setGoogleId($googleUser->getId());
            $user->setRefreshToken($accessToken->getRefreshToken());
            $this->em->flush();

            return $user;
        }));
    }

    public function onAuthenticationSuccess(...): RedirectResponse
    {
        return new RedirectResponse($this->router->generate('app_homepage'));
    }

    public function onAuthenticationFailure(...): Response
    {
        return new Response('Authentication failed', Response::HTTP_FORBIDDEN);
    }
}

3.5 Update security.yaml

security:
  enable_authenticator_manager: true

  firewalls:
    main:
      custom_authenticators:
        - App\Security\GoogleAuthenticator

  access_control:
    - { path: ^/connect, roles: PUBLIC_ACCESS }
    - { path: ^/, roles: ROLE_USER }

4. ✅ Summary

  • Installed knpu/oauth2-client-bundle and league/oauth2-google
  • Configured OAuth client in both Google Cloud and Symfony
  • Created routes for OAuth flow
  • Implemented a custom authenticator
  • Updated firewall and access controls

5. 🧭 Next Steps

  • Use access_type: offline and prompt: consent to obtain refresh tokens
  • Extend your User entity (add name, avatar, tokens…)
  • Protect app routes with ROLE_USER
  • Optionally integrate Tokens into other Google APIs like Calendar or Drive

Feedback welcome! Need help with refresh-token logic or multiple social logins? Just ask.

Keywords: Symfony OAuth2 Google, Symfony Google login, OAuth Symfony tutorial

Contents