2
votes

The following code uses the Google oauth2 mechanism to sign in a user. We need to process updates to the user's calendar while the user is offline, so we ultimately need the 'refresh token'. Does the result from grantOfflineAccess() return the refresh token (below, I can see that response.code holds a value that might be the refresh token)?

How can I get a refresh token that can be used (server side) to create new access keys for offline access to a user's Google calendar?

enter image description here

<script type="text/javascript">
    function handleClientLoad() {
        gapi.load('client:auth2', initClient);
    }

    function initClient() {
        gapi.client.init({
            apiKey: 'MY_API_KEY',
            clientId: 'MY_CLIENT_ID.apps.googleusercontent.com',
            discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest'],
            scope: 'https://www.googleapis.com/auth/calendar'
        }).then(function () {
            var GoogleAuth = gapi.auth2.getAuthInstance();
            GoogleAuth.signIn();
            GoogleAuth.grantOfflineAccess().then(function (response) {
                var refresh_token = response.code;
            });
        });
    }

</script>

<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
2

2 Answers

1
votes

There is a reason why you are having a problem getting a refresh token out of JavaScript. That reason being that it's not possible.

JavaScript is a client side programming language, for it to work you would have to have your client id and client secret embedded in the code along with the refresh token. This would be visible to anyone who did a view source on the web page.

I think you realize why that's probably a bad idea. The main issue is that gapi won't return it the library just doesn't have that ability (not that I have tried in raw JavaScript to see if the OAuth server would return it if I asked nicely).

You will need to switch to some server side language. I have heard that this can be done with Node.js, but haven't tried myself. And Java, PHP, Python are all valid options too.

0
votes

Based from this post, you should include the specific scopes in your requests. Your client configuration should have $client->setAccessType("offline"); and $client->setApprovalPrompt("force");.

After allowing access, you will be returned an access code that you can exchange for an access token. The access token returned is the one you need to save in a database. Later on, if the user needs to use the calendar service, you simply use the access token you already saved.

Here's a sample code:

/*
 * @$accessToken - json encoded array (access token saved to database)
*/

$client = new Google_Client();
$client->setAuthConfig("client_secret.json");
$client->addScope("https://www.googleapis.com/auth/calendar");

$_SESSION["access_token"] = json_decode($accessToken, true);

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

//REST OF THE PROCESS HERE