title: "invalid_grant" for Google SSO with Symfony4 and knpuniversity OauthBundle
body: <p>When I choose my email acount to log with google API, I have systematically a "invalid_grant" error.
  After debugging the GuardAuthenticator, everything's fine until retrieving user (it retrieves !) but when I return the user, I fall in onAuthenticationFailure with "invalid _grant" error.</p>
  
  <p>I'm working with Symfony 4.1 and Doctrine ODM : </p>
  
  <p>Here my code : </p>
  
  <p>knpu_oauth2_client.yaml : </p>
  
  <pre><code>knpu_oauth2_client:
    clients:
      google:
        # must be "google" - it activates that type!
        type: google
        # add and configure client_id and client_secret in parameters.yml
        client_id: "%env(GOOGLE_CLIENT_ID)%"
        client_secret: "%env(GOOGLE_CLIENT_SECRET)%"
        # a route name you'll create
        redirect_route: connect_google_check
        redirect_params: {}
        # Optional value for sending access_type parameter. More detail: https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters
        # access_type: ''
        # Optional value for sending hd parameter. More detail: https://developers.google.com/identity/protocols/OpenIDConnect#hd-param
        # hosted_domain: ''
        # Optional value for additional fields to be requested from the user profile. If set, these values will be included with the defaults. More details: https://developers.google.com/+/web/api/rest/latest/people
        # user_fields: {}
        # Optional value if you don't want or need to enable Google+ API access.
        # use_oidc_mode: false
        # whether to check OAuth2 "state": defaults to true
        # use_state: true
  
  </code></pre>
  
  <p>security.yaml : </p>
  
  <pre><code>security:
      encoders:
          FOS\UserBundle\Model\UserInterface: bcrypt
      providers:
          fos_userbundle:
              id: fos_user.user_provider.username_email
      firewalls:
          dev:
              pattern: ^/(_(profiler|wdt)|css|images|js)/
              security: false
          main:
              pattern: ^/(?!(api|connect))
              form_login:
                  provider: fos_userbundle
                  csrf_token_generator: security.csrf.token_manager
              anonymous: ~
              logout:
                  path: /logout
                  target: /login
              remember_me:
                  secret: '%env(APP_SECRET)%'
              guard:
                  authenticators:
                      - App\Security\GuardAuthenticator\GoogleAuthenticator
                      - App\Security\GuardAuthenticator\LoginFormAuthenticator
                      - lexik_jwt_authentication.jwt_token_authenticator
                  entry_point: App\Security\GuardAuthenticator\GoogleAuthenticator
          social:
              pattern: ^/connect/
              stateless: true
              anonymous: ~
              guard:
                  authenticators:
                      - App\Security\GuardAuthenticator\GoogleAuthenticator
  
      access_control:
           - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
           - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
           - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY }
           - { path: ^/api/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY }
           - { path: ^/connect/google, roles: IS_AUTHENTICATED_ANONYMOUSLY }
           - { path: ^/, roles: ROLE_USER }
           - { path: ^/api, roles: ROLE_USER }
  
  </code></pre>
  
  <p>GoogleAuthenticator : </p>
  
  <pre><code>&lt;?php
  declare(strict_types=1);
  
  namespace App\Security\GuardAuthenticator;
  
  use App\Document\User;
  use Doctrine\ODM\MongoDB\DocumentManager;
  use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
  use KnpU\OAuth2ClientBundle\Security\Authenticator\SocialAuthenticator;
  use League\OAuth2\Client\Provider\GoogleUser;
  use Symfony\Component\HttpFoundation\JsonResponse;
  use Symfony\Component\HttpFoundation\RedirectResponse;
  use Symfony\Component\HttpFoundation\Request;
  use Symfony\Component\HttpFoundation\Response;
  use Symfony\Component\Routing\Router;
  use Symfony\Component\Routing\RouterInterface;
  use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  use Symfony\Component\Security\Core\Exception\AuthenticationException;
  use Symfony\Component\Security\Core\User\UserInterface;
  use Symfony\Component\Security\Core\User\UserProviderInterface;
  use KnpU\OAuth2ClientBundle\Client\Provider\GoogleClient;
  
  class GoogleAuthenticator extends SocialAuthenticator
  {
      /**
       * @var ClientRegistry
       */
      protected $client;
      /**
       * @var DocumentManager
       */
      protected $documentManager;
      /**
       * @var Router
       */
      protected $router;
  
      public function __construct(
          ClientRegistry $client,
          DocumentManager $documentManager,
          RouterInterface $router
      ) {
          $this-&gt;client = $client;
          $this-&gt;documentManager = $documentManager;
          $this-&gt;router = $router;
      }
  
      /**
       * @param Request $request The request that resulted in an AuthenticationException
       * @param AuthenticationException $authException The exception that started the authentication process
       *
       * @return Response
       */
      public function start(
          Request $request,
          AuthenticationException $authException = null
      ) {
          return new JsonResponse(['message' =&gt; $authException-&gt;getMessage()], JsonResponse::HTTP_UNAUTHORIZED);
      }
  
      /**
       * @param Request $request
       *
       * @return bool
       */
      public function supports(Request $request): bool
      {
          return $request-&gt;attributes-&gt;get('_route') === 'connect_google_check';
      }
  
      /**
       * @param Request $request
       *
       * @return mixed Any non-null value
       *
       * @throws \UnexpectedValueException If null is returned
       */
      public function getCredentials(Request $request)
      {
          return $this-&gt;fetchAccessToken($this-&gt;getGoogleClient());
      }
  
      /**
       * @param mixed $credentials
       * @param UserProviderInterface $userProvider
       *
       * @throws AuthenticationException
       *
       * @return UserInterface|null
       */
      public function getUser($credentials, UserProviderInterface $userProvider)
      {
          /** @var GoogleUser $googleUser */
          $googleUser = $this-&gt;getGoogleClient()-&gt;fetchUserFromToken($credentials);
          $userEmail = $googleUser-&gt;getEmail();
  
          $user = $this-&gt;documentManager
              -&gt;getRepository(User::class)
              -&gt;findOneBy(['email' =&gt; $userEmail]);
  
          if ($user) {
              return $user;
          }
  
          return null;
      }
  
      /**
       * @param Request $request
       * @param AuthenticationException $exception
       *
       * @return JsonResponse
       */
      public function onAuthenticationFailure(
          Request $request,
          AuthenticationException $exception
      ): JsonResponse {
          return new JsonResponse(
              [
                  'message' =&gt; strtr(
                      $exception-&gt;getMessageKey(),
                      $exception-&gt;getMessageData())
              ],
              JsonResponse::HTTP_FORBIDDEN
          );
      }
  
      /**
       * @param Request $request
       * @param TokenInterface $token
       * @param string $providerKey The provider (i.e. firewall) key
       *
       * @return Response|null
       */
      public function onAuthenticationSuccess(
          Request $request,
          TokenInterface $token,
          $providerKey
      ) {
          $user = $token-&gt;getUser();
          $googleApiToken = $this-&gt;fetchAccessToken($this-&gt;getGoogleClient());
  
          $user-&gt;setApiToken($googleApiToken);
          $this-&gt;documentManager-&gt;persist($user);
          $this-&gt;documentManager-&gt;flush();
  
          return null;
      }
  
      /**
       * @return GoogleClient
       */
      private function getGoogleClient(): GoogleClient
      {
          return $this-&gt;client-&gt;getClient('google');
      }
  }
  
  </code></pre>
  
  <p>GoogleController.php : </p>
  
  <pre><code>&lt;?php
  declare(strict_types=1);
  
  namespace App\Controller;
  
  use App\Document\User;
  use App\Logger\PlanningLogger;
  use Doctrine\ODM\MongoDB\DocumentManager;
  use FOS\RestBundle\Controller\Annotations as Rest;
  use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
  use Psr\Log\LoggerInterface;
  use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  use Symfony\Component\HttpFoundation\RedirectResponse;
  use Symfony\Component\HttpFoundation\Request;
  use Symfony\Component\HttpFoundation\Session\SessionInterface;
  use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  
  class GoogleController extends AbstractController
  {
      /**
       * @var ClientRegistry
       */
      protected $clientRegistry;
  
      public function __construct(
          DocumentManager $documentManager,
          LoggerInterface $logger,
          ClientRegistry $clientRegistry
      ) {
          parent::__construct($documentManager, $logger);
          $this-&gt;clientRegistry = $clientRegistry;
      }
  
      /**
       * @Rest\Get("/connect/google", name="connect_google")
       *
       * @return RedirectResponse
       */
      public function connect()
      {
          return $this-&gt;clientRegistry-&gt;getClient('google')-&gt;redirect();
      }
  
      /**
       * @Rest\Get("/connect/google_check", name="connect_google_check")
       *
       * @param Request $request
       * @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
       */
      public function connectCheckAction(Request $request) {}
  }
  </code></pre>
  
  <p>I followed the documentation <a href="https://github.com/knpuniversity/oauth2-client-bundle" rel="nofollow noreferrer">oauth2-client-bundle</a> but I was not able to solve it.</p>
  
  <p>Someone could help me to solve this issue please ?</p>
  
  <p>Thanks !</p>