(仍未解决)授权Web客户端访问客户端和服务器端的用户Google日历?(使用Firebase和Google API)

mlb*_*mlb 7 javascript google-api google-authentication google-api-nodejs-client firebase-authentication

我有一个火力地堡的web应用程序,
并希望这样的任何用户可以登录并授权我的web应用程序访问他的谷歌日历(读/写)在客户端服务器端(管理日历,当用户在线时,当他的下线).


客户端.
Google开发者控制台上创建API密钥OAuth 2.0客户端ID(Web应用程序)后,我实现了以下代码:

首先,通过Firebase Authentification登录Google

firebase.initializeApp({apiKey: 'MY_WEB_APP_API_KEY'})
var provider = new firebase.auth.GoogleAuthProvider()
provider.addScope('https://www.googleapis.com/auth/calendar')
firebase.auth().signInWithPopup(provider)
Run Code Online (Sandbox Code Playgroud)

并且,要求授权我的Web应用程序可以使用Google Api JS客户端访问用户的Google日历

// https://apis.google.com/js/api.js
gapi.load('client:auth2', () => {
  gapi.auth2.authorize({
      scope: 'https://www.googleapis.com/auth/calendar',
      client_id: 'MY_WEB_APPL_CLIENT_ID',
      prompt: 'none',
      access_type: 'offline',
      include_granted_scopes: true
    }, () => {
      gapi.client.init({
        discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest']
      }).then(()  => {
        return gapi.client.calendar.events.list({
          calendarId: 'ANY_USER_CALENDAR_ID' // example: 123456789@group.calendar.google.com
        })
      }).then((resolve, reject) => {
        // IT WORKS ON CLIENT SIDE (RETURNS EVENTS LIST AS EXCEPTED)
      })
  })
})
Run Code Online (Sandbox Code Playgroud)

在这里,一切都在客户端作为例外(读取和写入连接的用户谷歌日历).


但现在,在服务器端.
Google开发者控制台上创建.json 服务帐户密钥(App Engine默认服务帐户)后,我在Firebase云功能上实现了google-api-nodejs-client,其代码如下:

const privatekey = require("./MY_WEB_APP_SERVICE_ACCOUNT_KEY.json")
const {google} = require('googleapis')
const jwtClient = new google.auth.JWT(
  privatekey.client_email,
  null,
  privatekey.private_key,
  ['https://www.googleapis.com/auth/calendar']
)
jwtClient.authorize()
const calendar = google.calendar('v3')

calendar.events.list({
  auth: jwtClient,
  calendarId: 'ANY_USER_CALENDAR_ID' // (in this case, the same previously used on client side: 123456789@group.calendar.google.com)
}).then((resolve, reject) => {
  // IT DOESNT WORKS ON SERVER SIDE (RETURNS 'Not Found' ERROR...)
})
Run Code Online (Sandbox Code Playgroud)

在这里验证工作正常,
calendar.events.list()返回"未找到"错误(谁不是真正有帮助......).


如果用户以前允许我的网络应用访问他的日历,那么
通过服务帐户读取或写入这些日历应该有效吗?

所以我不明白我错过或误解了什么?需要明确的代码才能继续前进.

希望我的解释足够清楚.

谢谢你的帮助!

Ger*_*rdo 2

当用户向您的应用程序授予权限(使用客户端 ID)时,您的应用程序将能够访问用户的信息,在本例中为日历。

但是,这不是通过服务帐户完成的,而是通过客户端 ID 完成的。

在您的服务器端代码(云功能)中,您似乎正在使用服务帐户对 Google 日历进行身份验证,这意味着您正在访问服务帐户的日历而不是在网络应用程序中进行身份验证的用户的日历(类似于常规的日历)帐户(服务帐户可以访问云端硬盘或日历等服务)。

您的服务帐户将无权访问用户的日历,除非用户向服务帐户提供/共享日历(类似于将日历共享给其他 Gmail 帐户)。

如果您想在服务器端访问该用户的日历,则需要将客户端上的 Google 身份验证返回的访问令牌和刷新令牌传递到您的服务器端。然后,您可以使用访问令牌代表用户调用日历。