I am building a SPA using vue.js which has a PHP backend server (slim framework 3). These are two separate projects, leave on two different servers and the backend has no front end at all.
SPA (vue.js) makes requests to backend via ajax.
Now I want to implement Google Calendar API to create a calendar and events every time user creates a todo item. To do that I need server to server access to Google Calendar API (I might need to make changes to the event on GCAL even if user is not logged in).
What I am trying to understand, how can I get the access token (and refresh token) using Google JS library using vue.js and save this in the db so that my backend can use it to make offline requests to GCAL Api.
When I use the Oauth v.2 using the JS library, all I get is the access_token which cannot be using for server to server communications.
[UPDATE]
Ok, a little bit more information. I am following the guides from Google and my front end looks like this at the moment jsbin
So I can successfully authorise user and access their calendar using the javascript sdk. But the token Javascript SDK returns is something like this
{
_aa: "1"
access_token: "xxxxxxx"
client_id: "yyyyyyyyyy"
cookie_policy: undefined
expires_at: "1456400189"
expires_in: "3600"
g_user_cookie_policy: undefined
issued_at: "1456396589"
response_type: "token"
scope: "https://www.googleapis.com/auth/calendar"
state: ""
status: Object
google_logged_in: false
method: "AUTO"
signed_in: true
token_type: "Bearer"
}
I send this token to my backend server and try to make a request to GCAL api as follows
$token = $request->getParam('token');
$client = new Google_Client();
$client->setApplicationName('Web');
$client->setScopes([Google_Service_Calendar::CALENDAR]);
$client->setAuthConfigFile(ROOT_DIR . '/client_secret.json');
$client->setAccessType('offline');
$client->setAccessToken(json_encode($token));
$service = new Google_Service_Calendar($client);
$calendarId = 'primary';
$optParams = array(
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => TRUE,
'timeMin' => date('c'),
);
$results = $service->events->listEvents($calendarId, $optParams);
And it returns error saying the token is expired. I checked the Google Code and found out the reason it returns this error is because of these lines
public function isAccessTokenExpired()
{
if (!$this->token || !isset($this->token['created'])) {
return true;
}
// If the token is set to expire in the next 30 seconds.
$expired = ($this->token['created']
+ ($this->token['expires_in'] - 30)) < time();
return $expired;
}
As you can see the token that comes from the front end doesn't have created
field as well as no refresh_token
field.
Thanks for updating the question! I am thinking the issue is that using the client-side flow does not allow you to get a refresh token. From the docs:
OAuth 2.0 client-side flow (AKA Implicit flow) is used to obtain access tokens (it does not support the issuance of refresh tokens) and is optimized for public clients known to operate a particular redirection URI. These clients are typically implemented in a browser using a scripting language such as JavaScript.
The authorization server MUST NOT issue a refresh token.
see for more: How to get refresh token while using Google API JS Client
You'd need to use the server-auth flow to get a token you can refresh and use long-term. Here's a quickstart guide for PHP.
One other thing to consider is that you will only receive a refresh_token
the first time someone authorizes your app. After that, auth attempts will only return an access token. So if you lose the refresh token, you will need to either disable the authorization from your google account, or use the "force re-auth" option in the API.