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

7
我有一个Firebase web应用程序, 希望任何用户都可以登录并授权我的web应用程序访问他的Google日历(读/写)在客户端和服务器端(在线和离线时管理日历)。
在客户端方面,在Google Developers Console上创建一个API密钥和一个OAuth 2.0客户端ID(Web应用程序)后,我实现了以下代码:
首先,通过Firebase身份验证使用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)

同时,请求授权让我的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)
      })
  })
})

在这里,客户端的所有功能都可以正常工作(读取和写入连接用户的Google日历)。

但现在,关于服务器端
Google开发者控制台上创建了一个.json服务帐号密钥(App Engine默认服务帐号)后,我已经在Firebase Cloud Functions上实现了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...)
})

在这里认证已经生效
但是calendar.events.list()返回一个'Not Found'错误(并不是很有帮助...)。


如果用户先前允许我的Web应用访问他的日历,那么通过服务帐户读取或写入这些日历应该可以工作?
所以我不明白我错过了什么或误解了什么?需要明确的代码才能继续前进。
希望我的解释足够清楚。
感谢您的帮助!
1个回答

2
当用户授予您的应用程序权限(使用客户端ID),您的应用程序将能够访问用户的信息,此处为日历。
但是,这不是通过服务帐户完成的,而是通过客户端ID完成的。
在您的服务器端代码(云函数)中,似乎您正在使用服务帐户进行Google日历身份验证,这意味着您正在访问服务帐户的日历,而不是在Web应用程序中经过身份验证的用户的日历(类似于常规帐户,服务帐户可以访问诸如Drive或Calendar之类的服务)。
除非用户与服务帐户共享日历(类似于将日历分享给其他Gmail帐户),否则您的服务帐户将无法访问用户的日历。
如果您想在服务器端访问该用户的日历,则需要将Google身份验证返回的访问令牌和刷新令牌从客户端传递到服务器端。然后,您可以使用访问令牌代表用户调用日历。

谢谢Gerardo,但我认为我需要一些明确的代码来理解,因为我在google-node-api存储库中找不到任何关于将现有令牌传递给JWT Auth(服务器端)的文档;而在客户端,我只有一个刷新令牌(没有访问令牌)... - mlb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接