How can access google calendar of user and edit it without asking for user permisssion again and again

Viewed 130

On my website, I am asking for google calendar access. I can edit the user calendar but, I don't want to ask for user permission, again and again, so once the user authorized and give access to google calendar, I can edit it anytime until the user revokes the access. Should I implement it on the frontend or the backend and how? I checked few answers where they mention we can use a service account but, it is not clear how can I edit or read the individual user's calendar events and how can I remove it once the user revokes access. This question was deleted because code was missing so adding code below.

I tried this so once user login I get access token and I am using it

window.gapi.load("client:auth2", () => {
  window.gapi.client.setApiKey("api_key");
  window.gapi.client.load("https://content.googleapis.com/discovery/v1/apis/calendar/v3/rest")
  .then(() => {
    window.gapi.auth.setToken({ access_token: access_token })
    window.gapi.client.calendar.events.insert({
      "calendarId": "id",
      'resource': event
    }).then((res) => {
      console.log("calendar data res "+JSON.stringify(res))
    }).catch(err => console.log("error getting calendar data "+JSON.stringify(err)))
  }).catch(err => console.error("Error loading GAPI client for API", err) )
})

but once access token expires how can I get a new access token( I don't want to show login popup to the user again and again. I want to know how can I do it using refresh token on client-side).

2 Answers

You can't get a refresh token on the client-side without exposing your secret key to the public.

You can create an endpoint that accepts oAuth code and return the token, save the refresh token for later. You set up a corn job that checks for expired token and refreshes them.

Every time the user accesses your app, you grab a fresh token from the server and proceed to work normally.

As per Google guidelines. You do POST to https://oauth2.googleapis.com/token. Assuming your server-side stack is in Node.js, you do something like this using an HTTP client like Axios:

const Axios = require('axios');
const Qs = require('querystring');

const GOOGLE_CLIENT_ID = 'abc';
const GOOGLE_CLIENT_SECRET = '123';

let refreshToken = getFromDataBase(); // should be stored in database

Axios.post('https://oauth2.googleapis.com/token', Qs.stringify({
    client_id: GOOGLE_CLIENT_ID,
    client_secret: GOOGLE_CLIENT_SECRET,
    refresh_token: refreshToken,
    grant_type: 'refresh_token'
}), {
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
    }
})
.then(({ data }) => console.log(data.access_token)) // new token that expires in ~1 hour
.catch(console.log)

Firstly, do you (a) want to update the calendar when the user is not logged in, for example in response to an external event? ... OR ... do you (b) only want to update the calendar from within a browser session?

If (a), then you need to ask the user for offline access which will give you a Refresh Token , which you can securely store on a server and use whenever you need to. (Forget all about Service Accounts).

If (b), then you need the following pieces of information :-

  1. When the access token expires, request access again, but add the flag prompt=none. This will give you a fresh Access Token without the user seeing any UX.
  2. Do this in a hidden iframe so that it is happening in the background and is invisible to the user. Your iframe will therefore always have an up to date Access Token which it can share with your app via localStorage or postMessage.
Related