Google Auth, Login and Calendars Help

Hi All,

I was wondering if someone could point me in the right direction with this. I’ve almost got things working, but I have one quirk that tells me that I have something fundamentally wrong somewhere along the way.

In my Meteor web app that I have created, I’m using Google to sign in. The app fetches info from the user’s Google calendar too, and I’m using the Google APIs to do that. All that is working, but there seems to be a disconnect between permissions.

If I use a browser that has never been used previously to log into Google (e.g. using Chrome incognito or guest) then logging onto my app allows it to get calendar info.

If I use a browser that has previously logged into a Google account, that also works.

But if I log into my app with 1 Google ID, then log out, and log back in again with a different Google ID, the new user actually gets access to the 1st user’s calendar!

If, in my app I use the API to sign out gapi.auth2.getAuthInstance().signOut() it will prevent calendar access (it doesnt sign out of my app, but deauthenticates calendar access. But then when I log out of my app, and log back in again, I still have no calendar access.

In summary, logging into my app using a ‘fresh’ browser, grants my app calendar access, but only for the first user that logs into the app…?

Any pointers?

Could be a problem of access token and refresh token?! https://developers.google.com/calendar/auth

I suppose you would need to make sure your access token is always valid and of the current google user authenticated. This is some code that I wrote some time back but I think it tells the story:


     let GoogleAuth
      const SCOPE = 'profile email https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/contacts.readonly'

    // main function to run after I pull the library down async. I don't use an NPM for this library  
    const handleClientLoad = () => {
        gapi.load('client:auth2', () => {
          const discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest'
          gapi.client.init({
            apiKey: 'AIzaxxxxxxxx',
            discoveryDocs: [discoveryUrl],
            clientId: 'yyyyyyyy.apps.googleusercontent.com',
            scope: SCOPE
          }).then(() => {
            GoogleAuth = gapi.auth2.getAuthInstance()
            const user = GoogleAuth.currentUser.get()
            // console.log('this is the user: ', user, user.El)
            if (user.El) {
              const accessToken = user.Zi.access_token
              // do something with the access token, call what you need to call from google.
            } else {
              GoogleAuth.signIn()
                .then(() => {
                  const user = GoogleAuth.currentUser.get()
                  // console.log('this is the user but in the second phase: ', user, user.El)
                  if (user.El) {
                    const accessToken = user.Zi.access_token
                     // do something with the access token, call what you need to call from google.
                  }
                })
            }
          })
        })
      }

      // load the google API and insert the script in the head somewhere
      if (!document.getElementById('google-jsapi')) {
        (function (d, s, id) {
          var js; var gjs = d.getElementsByTagName(s)[0]
          // if (d.getElementById(id)) { return }
          js = d.createElement(s); js.id = id
          js.src = 'https://apis.google.com/js/api.js'
          js.onload = () => { handleClientLoad() }

          js.onreadystatechange = () => { if (this.readyState === 'complete') { script.onload() } }

          gjs.parentNode.insertBefore(js, gjs)
        }(document, 'script', 'google-jsapi'))
      } else {
        handleClientLoad()
      }
    }

Thanks @paulishca, but I think I have sorted it out. 2 days of messing about, then 20 mins after I made this post, I took a different approach (with the help of a package) and got it sorted! I really didn’t want to bother people in a forum, and it looks like just 20 more mins of frustration would have prevented that. Oh well, hopefully this post will help someone else out in the future.

For anyone else that hits this problem, here’s a bit of background…

I had implemented Google sign on following the Meteor Docs, and that worked like a dream. However, when it came to using the Google API for anything else within my App, I found documentation to be really rather sparse (other than the excellent google api docs - what I mean is how to use them in your Meteor app specifically), so I just hacked away until I got something I thought was working. This is what I was doing…

To access the calendar info, I was sort of using a NPM package called react-google-calendar-api. I really just looked at the code and ripped the bits out of it I needed to start to learn. The problem was that the code I produced for that (or if I had just installed that package) was getting it’s own tokens, and not using the ones Meteor had stored for the user in the User collection. That had a funny effect of independently authenticating access outside of my App, so switching users or messing with sign-in/out in any way didn’t keep things in sync with my Meteor logged in user. I played for a bit trying to fetch the token from the users collection into the code I created based on react-google-calendar-api, but I couldn’t figure out how I could use that with the token. TBH, I don’t think you can.

This is how I got it working…

In another thread in this forum, someone mentioned the package danopia:google-api. That ties the users collection data with a wrapper to Google API. In other words, it forces any API requests to use the token on the actual logged in user - just what I wanted. It also sorts out any problems with outdated tokens behind the scenes so I don’t need to worry about that either! Perfect!

1 Like