vendor/uvdesk/core-framework/Controller/GoogleSSO.php line 54

Open in your IDE?
  1. <?php
  2. namespace Webkul\UVDesk\CoreFrameworkBundle\Controller;
  3. use League\OAuth2\Client\Provider\Google;
  4. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  5. use Symfony\Component\HttpFoundation\Request;
  6. use Symfony\Component\HttpFoundation\RedirectResponse;
  7. use Symfony\Component\HttpFoundation\Response;
  8. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  9. class GoogleSSO extends AbstractController
  10. {
  11.     private string $googleClientId;
  12.     private string $googleClientSecret;
  13.     private string $googleRedirectUri;
  14.     private \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $tokenStorage;
  15.     private \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher;
  16.     private \Doctrine\ORM\EntityManagerInterface $entityManager;
  17.     private \Symfony\Component\Security\Core\User\UserProviderInterface $userProvider;
  18.     public function __construct(
  19.         string $googleClientId,
  20.         string $googleClientSecret,
  21.         string $googleRedirectUri,
  22.         \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $tokenStorage,
  23.         \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher,
  24.         \Doctrine\ORM\EntityManagerInterface $entityManager,
  25.         \Symfony\Component\Security\Core\User\UserProviderInterface $userProvider
  26.     ) {
  27.         $this->googleClientId     $googleClientId;
  28.         $this->googleClientSecret $googleClientSecret;
  29.         $this->googleRedirectUri  $googleRedirectUri;
  30.         $this->tokenStorage       $tokenStorage;
  31.         $this->eventDispatcher    $eventDispatcher;
  32.         $this->entityManager      $entityManager;
  33.         $this->userProvider       $userProvider;
  34.     }
  35.     private function getGoogleProvider(): Google
  36.     {
  37.         return new Google([
  38.             'clientId'     => $this->googleClientId,
  39.             'clientSecret' => $this->googleClientSecret,
  40.             'redirectUri'  => $this->googleRedirectUri,
  41.             'scopes'       => ['openid''email''profile'],
  42.         ]);
  43.     }
  44.     /**
  45.      * STEP 1: Redirect user to Google
  46.      * Route name example: helpdesk_member_google_login
  47.      */
  48.     public function googlelogin(SessionInterface $session): RedirectResponse
  49.     {
  50.         $provider $this->getGoogleProvider();
  51.         // Generate authorization URL
  52.         $authUrl $provider->getAuthorizationUrl();
  53.         // Save state in session for CSRF protection
  54.         $session->set('oauth2state'$provider->getState());
  55.         // Redirect to Google
  56.         return new RedirectResponse($authUrl);
  57.     }
  58.     /**
  59.      * STEP 2: Google redirects back here with ?code= and ?state=
  60.      * Route name example: helpdesk_member_google_callback
  61.      */
  62.     public function googlecallback(
  63.         Request $request
  64.         SessionInterface $session
  65.     ): Response
  66.     {
  67.         $provider $this->getGoogleProvider();
  68.         // 1) Handle Google error
  69.         if ($request->query->has('error')) {
  70.             $error $request->query->get('error');
  71.             return new Response(
  72.                 'Got error from Google: ' htmlspecialchars($errorENT_QUOTES'UTF-8'),
  73.                 400
  74.             );
  75.         }
  76.         // 2) Ensure we have an authorization code
  77.         if (!$request->query->has('code')) {
  78.             return new Response('No authorization code returned from Google.'400);
  79.         }
  80.         // 3) Validate state (CSRF protection)
  81.         $state        $request->query->get('state');
  82.         $sessionState $session->get('oauth2state');
  83.         if (empty($state) || $state !== $sessionState) {
  84.             $session->remove('oauth2state');
  85.             return new Response('Invalid state – possible CSRF.'400);
  86.         }
  87.         try {
  88.             // 4) Exchange code for access token
  89.             $token $provider->getAccessToken('authorization_code', [
  90.                 'code' => $request->query->get('code'),
  91.             ]);
  92.             // 5) Get user details from Google
  93.             $owner $provider->getResourceOwner($token);
  94.             $googleEmail $owner->getEmail();
  95.             // 6) Load local user via UserProvider (handles roles, instances, validation)
  96.             try {
  97.                 $user $this->userProvider->loadUserByUsername($googleEmail);
  98.             } catch (\Symfony\Component\Security\Core\Exception\UsernameNotFoundException $e) {
  99.                 return new Response("User with email $googleEmail not found or not active."403);
  100.             }
  101.             // 7) Programmatic Login
  102.             $firewallName 'back_support'
  103.             
  104.             // Roles are already set by UserProvider::loadUserByUsername
  105.             $token = new \Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken(
  106.                 $user
  107.                 null
  108.                 $firewallName
  109.                 $user->getRoles()
  110.             );
  111.             // Set token in storage
  112.             $this->tokenStorage->setToken($token);
  113.             // Set session attribute for serialization
  114.             $sessionKey '_security_' $firewallName;
  115.             $serializedToken serialize($token);
  116.             $session->set($sessionKey$serializedToken);
  117.             $session->save(); 
  118.             // DEBUG LOGGING
  119.             error_log("GoogleSSO: Logged in user {$user->getEmail()}");
  120.             error_log("GoogleSSO: Roles: " implode(','$user->getRoles()));
  121.             // Dispatch interactive login event
  122.             $event = new \Symfony\Component\Security\Http\Event\InteractiveLoginEvent($request$token);
  123.             $this->eventDispatcher->dispatch($event'security.interactive_login');
  124.             // 8) Redirect
  125.             return $this->redirect('/public/en/member/dashboard');
  126.         } catch (\Exception $e) {
  127.             return new Response('Something went wrong: ' $e->getMessage(), 500);
  128.         }
  129.     }
  130. }