Get an authenticated Google API client in Laravel

  google-api, google-calendar-api, laravel, oauth-2.0, php

I’m trying to build an app which is supposed to be able to create a calendar for some of my users, and add/delete events in it.

I want to use Google Calendar for this, and I’m having issues with the authentication part. I installed the vendor and here is my code:

I have this method in my controller:

    /**
     * Create the Google calendar if not exists.
     *
     * @return RedirectResponse
     */
    public function createCalendar(Request $request, Expert $expert, GoogleClientProvider $googleClientProvider): RedirectResponse
    {
        $client = $googleClientProvider->getAuthenticatedClient($request);

        $calendarService = new Google_Service_Calendar($client);

        $calendar = new Google_Service_Calendar_Calendar();
        $calendar->setSummary('Chosen');
        $calendar->setTimeZone('Europe/Paris');

        $calendarService->calendars->insert($calendar);

        return redirect('experts.show', ['expert' => $expert]);
    }

And this code in a service:


class GoogleClientProvider
{
    private $client;

    public function __construct(Google_Client $client)
    {
        $this->client = $client;
    }

    /**
     * Returns an authorized API client.
     * @return Google_Client the authorized client object
     */
    function getAuthenticatedClient(Request $request)
    {
        if (!empty($request->get('error'))) {
            return redirect(route('welcome'))->with('error', 'You need to authorize access to your calendars');
        }

        // Load previously authorized token from a file, if it exists.
        // The file token.json stores the user's access and refresh tokens, and is
        // created automatically when the authorization flow completes for the first
        // time.

        //TODO CHECK IF TOKEN EXISTS IN SESSION


        // If there is no previous token or it's expired.
        if ($this->client->isAccessTokenExpired()) {
            // Refresh the token if possible, else fetch a new one.
            if ($this->client->getRefreshToken()) {
                $this->client->fetchAccessTokenWithRefreshToken($this->client->getRefreshToken());
            } else {
                $this->client->setAuthConfig('credentials.json');
                $this->client->addScope(Google_Service_Calendar::CALENDAR);
                $this->client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
                $this->client->setAccessType('offline');
                $this->client->setIncludeGrantedScopes(true);

                if (empty($request->get('code'))) {
                    return redirect($this->client->createAuthUrl());
                }

                // Exchange authorization code for an access token.
                $accessToken = $this->client->fetchAccessTokenWithAuthCode($request->get('code'));
                $this->client->setAccessToken($accessToken);

                // Check to see if there was an error.
                if (array_key_exists('error', $accessToken)) {
                    throw new RuntimeException(join(', ', $accessToken));
                }
            }
            //TODO STORE TOKEN IN SESSION
        }
        return $this->client;
    }
}

As you can see, I might have to do a redirection (to get the ‘code’ essentially). But this shouldn’t be in a service. I’m also not sure what I should put in the "redirectUri". How can I organize my code to do this properly, and be able to get an authenticated client ?

Source: Laravel

Leave a Reply