FOSOUserBundle + HWIOAuthBundle google accesstoken Timeout after a hour

1k Views Asked by At

Iam using FOSUserBundle + HWIOAuthBundle and have a problem regarding the accesstoken expired after one hour. Here I am saving my access token in db while each login. How to refresh my access token and update in db? is there any document regarding this?

1

There are 1 best solutions below

0
On

I ran into this problem recently! Was using the stored access token to get contacts.

In the service that gets the contacts, it tries with the currently saved token, and if that doesn't work out, it leverages the user's refresh token to generate a new access token.

My travels led me to a setup like this, but I didn't capture the refresh token on signup. So until I had that figured out, I was euchred.

Additionally, you'll need to ask for 'offline' access in the scope, when defining the google resource in HWIOauth, if you want access to that refresh token.

Contact Retrieving Service:

<?php

namespace Acme\DemoBundle\Services;
use Acme\DemoBundle\Entity\User;

class GoogleContactRetriever
{

    private $user;

    private $buzz;

    public function __construct($buzz, $googleId, $googleSecret, $userProvider)
    {
        $this->buzz = $buzz;
        $this->googleId = $googleId;
        $this->googleSecret = $googleSecret;
        $this->userProvider = $userProvider;
    }

    public function setUser($user)
    {
        $this->user = $user;
    }

    public function requestContacts()
    {
        return $this->buzz->get( "https://www.google.com/m8/feeds/contacts/default/full?access_token=".$this->user->getGoogleAccessToken() );
    }

    public function retrieveUserContacts()
    {
        $response = $this->requestContacts();

        $headers = $response->getHeaders();

        if ($headers[0] != 'HTTP/1.0 200 OK') {
            $this->refreshAccessToken($this->user);
            $response = $this->requestContacts();
        }

        return $this->parseResponseString($response->getContent());
    }

    // ...

    public function refreshAccessToken($user)
    {
        $refreshToken = $user->getGoogleRefreshToken();

        $response = $this->buzz->post( "https://accounts.google.com/o/oauth2/token", array(),
            "refresh_token=$refreshToken&client_id={$this->googleId}&client_secret={$this->googleSecret}&grant_type=refresh_token"
        );

        $responseContent = json_decode($response->getContent());

        $this->userProvider->updateGoogleAccessToken($user, $responseContent->access_token);
    }

}

FOSUBProvider

<?php
namespace NYW\Bundle\CoreBundle\Security\Core\User;

use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseClass;
use Symfony\Component\Security\Core\User\UserInterface;

class FOSUBUserProvider extends BaseClass
{

    /**
     * {@inheritdoc}
     */
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
    {
        $serviceName = $response->getResourceOwner()->getName();

        $avatar = null;
        $username = $response->getUsername();

        $email = $response->getEmail();
        $user = $this->userManager->findUserByEmail($email);
        //when the user is registrating
        if (null === $user) {

            $service = $response->getResourceOwner()->getName();

            $setter = 'set'.ucfirst($service);
            $setter_id = $setter.'Id';
            $setter_token = $setter.'AccessToken';
            // create new user here
            $user = $this->userManager->createUser();
            $user->$setter_id($email);
            $user->$setter_token($response->getAccessToken());

            switch ($service) {
                case 'google':
                    $refreshToken = $response->getRefreshToken();
                    $user->setGoogleRefreshToken($refreshToken);
                break;
            }

            //I have set all requested data with the user's username
            //modify here with relevant data
            $user->setUsername($username);
            $user->setEmail($email);
            $user->setPassword($email);
            $user->setEnabled(true);
            $this->userManager->updateUser($user);

            return $user;
        }

        //We used to call the parent's loadUserByOAuthUserResponse method here..

        $setter = 'set' . ucfirst($serviceName) . 'AccessToken';

        //update access token
        $user->$setter($response->getAccessToken());

        return $user;
    }

    public function updateGoogleAccessToken($user, $token)
    {
        $user->setGoogleAccessToken($token);
        $this->userManager->updateUser($user);
    }

}

config.yml

services:
    adb.user_provider:
        class: "Acme\DemoBundle\Security\Cure\FOSUBUserProvider"
            arguments: [@fos_user.user_manager,{facebook: facebook_id, google: google_id}]

hwi_oauth:
    connect:
        account_connector: adb.user_provider
    resource_owners:
        google:
            scope: "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.google.com/m8/feeds"