0

I'm using Google Calendar API to display events on fullcalendar (so using a json object in my view). I'm using codeigniter php framework, and I have a few functions in my controller to create a new client then I use that in the oauth2callback() function to exchange my code for an access_token then I start calling the service in gcalendar() and gcalendar_events. I have set the accessType to offline but that doesn't seem to make me access the events offline. It works great except that I'm redirected to log in again every time the session ends. I don't want that, I want them to display all the time after the session ends. I am trying to use a refresh token in case the access_token expires to see if that would fix the problem.

this is the code in my controller

    function getClient() {
        $client = new Google_Client();
        $client->setApplicationName("DL Calendar");
        $client->setAuthConfig('application/client_secrets.json');
        $client->addScope('profile');
        $client->setIncludeGrantedScopes(true);
        $client->setAccessType('offline');

        return $client;
}

  function gcalendar() {
    $this->load->add_package_path(APPPATH . 'vendor/autoload');

    $client = $this->getClient();
    //$client->setRedirectUri(site_url('calendar/index'));
    $client->addScope(Google_Service_Calendar::CALENDAR);

    if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {

        $client->setAccessToken($_SESSION['access_token']);
        $access_token = $_SESSION['access_token'];

        $service = new ]Google_Service_Calendar($client);                    
        $calendar = new Google_Service_Calendar_Calendar();
                //$calendarList = $service->calendarList->listCalendarList();
        $calendar = $service->calendars->get('primary');

               $params = array(
                    'owner_id' => get_current_user_id(),
                    'title' => get_current_user(). ' ' .'Google Calendar',
                    'type' => 'gcal',
                    'url' => $calendar->id,   
                );

        $calendar_id = $this->Calendar_model->add_calendar($params); 
        redirect('calendar/index');

    } else {

        $redirect_uri = site_url('calendar/oauth2callback');
        header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
     }
        $this->session->set_flashdata('success', 'Event Successfully Added');
}

function oauth2callback() {

    //Build the client object
        $client = $this->getClient();
        $client->addScope(Google_Service_Calendar::CALENDAR); 
        $service = new Google_Service_Calendar($client);

        $url = parse_url($_SERVER['REQUEST_URI']); parse_str($url['query'], $params);
        $code = $params['code'];

    //To exchange an authorization code for an access token, use the authenticate method:
        if (! isset($code)) {
            $auth_url = $client->createAuthUrl();
            header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

        } else {

            $token = $client->fetchAccessTokenWithAuthCode($code);     
            $client->setAccessToken($token);
            $client->authenticate($code);      
            $_SESSION['access_token'] = $client->getAccessToken();
            $redirect_uri = site_url('calendar/gcalendar');
            header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
         }              

}

function gcalendar_events() {
    $client = $this->getClient();

    $client->addScope(Google_Service_Calendar::CALENDAR);
   // $client->setRedirectUri(site_url('calendar/gcalendar'));
    $client->setAccessType('offline'); //need calendar events to appear even if not logged in to google     
    if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {

        $client->setAccessToken($_SESSION['access_token']);      
        $access_token = $_SESSION['access_token'];

        $service = new Google_Service_Calendar($client);
        $id = 'primary';   
        $calendar = new Google_Service_Calendar_Calendar();
        $calendar = $service->calendars->get('primary');

        $event = new Google_Service_Calendar_Event();

        $events = $service->events->listEvents($id);

            foreach ($events->getItems() as $event) {          

                $startTime = strtotime($event->getStart()->dateTime)  ;
                $endTime = strtotime($event->getEnd()->dateTime);
                $start = date('Y-m-d H:i:s', $startTime);
                $end = date('Y-m-d H:i:s', $endTime);

                $eventsArr[] = array(
                                'title' => $event->getSummary(),               
                                'start'=> $start,                   
                                'end' =>  $end,
                            ); 
                        }  
                        // Return a single `events` with all the `$eventsArr`
                        echo json_encode($eventsArr);


    }
}

Is the problem in my session ending? or does the access token expire and I need a refresh token? where do I set the refresh token cause I tried putting it in more that one place and I get an error message that refresh token has to be set as part off setAccessToken. I put it all over and still got error messages.

Here is the code I used

     if ($client->isAccessTokenExpired()) {
                            $refresh_token =     $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
                            $client->setAccessToken($refresh_token);
                            $_SESSION['access_token'] = $refresh_token;
                            $this->load->helper('file');
                         write_file('application/client_secrets.json',   json_encode($client->getAccessToken()));
     } else {
        $access_token = $_SESSION['access_token'];
            }

I just noticed that it once used to say 'grant offline access' in my authorization but now it no longer mentions that while google documentation says "After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed."

enter image description here

Cœur
  • 32,421
  • 21
  • 173
  • 232
nivanmorgan
  • 149
  • 1
  • 12

1 Answers1

0

During your first authorization with Google, you will receive a token that will expire in 3600 seconds or one hour. So you need to use refresh token to get a new working token.

It is something like this SO question.

$token = $client->getAccessToken();
$authObj = json_decode($token);
if(isset($authObj->refresh_token)) {
save_refresh_token($authObj->refresh_token);
}

Make sure you save this refresh_token.

You can update it with:

$client->refreshToken($your_saved_refresh_token);

And then set your new access token to the session:

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

I also suggest you to visit this quickstart of Google Calendar for PHP.

For more information, check this related SO question.

Community
  • 1
  • 1
KENdi
  • 7,205
  • 2
  • 14
  • 26
  • I'm sorry I'd given up on anyone answering the post but I got your answer yesterday and it worked to get the events but now I'm getting this error which is very easy but I can't find documentation for.

    Message: { "error": "invalid_request", "error_description": "Required parameter is missing: grant_type", "error_uri": ""

    @KENdi .. do you know anything about the parameter .. can't find documentation on it. Thanks for the awesome answer. it was very clear
    – nivanmorgan Oct 28 '16 at 14:34