20

I started to configure google calendar on my new application. I almost made an exact copy of the authentication code displayed at google developers ( https://developers.google.com/google-apps/calendar/instantiate ), but i keep getting the following error:

Error fetching OAuth2 access token, message: 'invalid_grant'

I'm currently using Fork-CMS ( http://www.fork-cms.com ), a young lightweigth CMS. I correctly configured the config.php file of the google-api-php-client. (client-id, client-secret, redirect-uri, development key,...) and the redirect uri is correctly set on the google api's console. My code looks as follows:

<?php

/**
* This is a widget with a calendar implementation.
*
* @package       frontend
* @subpackage    events
*
* @author        Michiel Vlaminck <michielvlaminck@gmail.com>
*/
class FrontendEventsWidgetCalendar extends FrontendBaseWidget
{

    private $events = array();
    private $authUrl = array();

    /**
    * Execute the extra
    *
    * @return    void
    */
    public function execute()
    {      
        // call parent
        parent::execute();

        // load template
        $this->loadTemplate();

        // get data
        $this->getData();

        // parse
        $this->parse();
    }


    /**
    * Get the data from Google Calendar
    * This method is only executed if the template isn't cached
    *
    * @return    void
    */
    private function getData()
    {
        require_once PATH_LIBRARY . '/external/google-api-php-client/src/apiClient.php';
        require_once PATH_LIBRARY . '/external/google-api-php-client/src/contrib/apiCalendarService.php';

        $client = new apiClient();

        $service = new apiCalendarService($client);

        if (isset($_SESSION['oauth_access_token'])) {
            $client->setAccessToken($_SESSION['oauth_access_token']);
        } else {
            $token = $client->authenticate();
            $_SESSION['oauth_access_token'] = $token;
        }

        if ($client->getAccessToken()) {

            $calId = FrontendEventsModel::getCalendarId((int) $this->data['id']);
            $calId = $calId[0]['calendar_id'];

            $events = $service->events->listEvents($calId);
            $this->events = $events['items'];

            $_SESSION['oauth_access_token'] = $client->getAccessToken();

        } else {
            $this->authUrl = $client->createAuthUrl();
        }
    }


    /**
    * Parse
    *
    * @return    void
    */
    private function parse()
    {
        $this->tpl->assign('events', $this->events);
        $this->tpl->assign('authUrl', $this->authUrl);
    }
}

?>

When I open this widget-page for the first time, I get directed to google to authenticate the application. When I agree, I get redirected to my application and that's the point where I'm getting:

apiAuthException » Main

Message Error fetching OAuth2 access token, message: 'invalid_grant'
File    C:\wamp\www\Officevibes\library/external\google-api-php-client\src\auth\apiOAuth2.php
Line    105
Date    Thu, 05 Apr 2012 08:34:47 +0000
URL http://localhost/calendar?code=4/YPUpFklKvhEeTcMm4moRth3x49oe
Referring URL   (Unknown)
Request Method  GET
User-agent  Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.142 Safari/535.19
Kara
  • 5,650
  • 15
  • 48
  • 55
Michiel
  • 201
  • 1
  • 2
  • 5

6 Answers6

22

You should reuse the access token you get after the first successful authentication. You will get an invalid_grant error if your previous token has not expired yet. Cache it somewhere so you can reuse it.

janmoesen
  • 7,490
  • 1
  • 21
  • 18
  • 7
    I think this is no longer true. Using a refresh token, I was able to get an access token, and then another one before the first one expired. (I think this can be seen in OAuth 2.0 Playground also - https://developers.google.com/oauthplayground/ ). – user637563 Nov 17 '13 at 17:39
  • Actually.. Im able to use the refresh_token to generate more access_tokens even if the current one hasnt expired. It will just give me a new access_token, and the previous one is still valid. So... Im not sure what you are saying is accurate. – omarojo Dec 04 '15 at 00:10
  • That could very well be. I answered truthfully based on my experience back then. This is an ancient answer in Internet time. Things might have changed in the meanwhile. – janmoesen Jan 21 '16 at 10:19
9

I was having a similar problem caused by the time on my server being incorrect. Make sure your system clock is synchronised.

Sio
  • 1,269
  • 1
  • 11
  • 19
  • It was the problem I had as well. I am using a virtual machine to run the API on. directly after wake-up the time isn't synchornized yet. – Rias Mar 31 '15 at 16:53
  • 1
    I have tried many solution. This is the last solution I havent tried because I dont understand. What do you mean by "time on server being incorrect"? How to check if the system clock is synchornised? – John Apr 22 '16 at 07:57
  • I'd like to know too @John – Brett Apr 28 '16 at 13:49
  • I did the following to sync time on my Ubuntu Linux server which worked for me(assuming you do not have network time protocol(ntp) daemon installed): sudo apt-get install ntp; sudo service ntp stop; sudo ntpdate -s time.nist.gov; sudo service ntp start – penguin4hire Mar 07 '17 at 02:47
8

Go to your Google API Console ( https://code.google.com/apis/console/ ) and revoke your Client Secret under Client ID for installed applications.

Be sure to also update your code with the new Client Secret

Zach M.
  • 129
  • 1
  • 2
3
  1. Go to security.google.com
  2. Revoke access
  3. visit the authentication url again
  4. you will now get a new refreshtoken
1

You'll also receive this error if you mistakenly try to authenticate your ID Token, rather than your Access Token.

So don't be like me - Make sure you pass the correct token into your code!

Matt
  • 3,523
  • 3
  • 21
  • 22
0

I had a similar issue. The problem with "invalid_grant" is that it's basically a placeholder for any error that occurs in relation to the token. I found this article to be really helpful.

zomnombom
  • 937
  • 1
  • 9
  • 15