我有一个Firebase网络应用,
并且希望任何用户都可以登录并授权我的网络应用访问客户端和服务器端的Google日历(读/写)(以便在用户上线和离线时管理日历).
并且希望任何用户都可以登录并授权我的网络应用访问客户端和服务器端的Google日历(读/写)(以便在用户上线和离线时管理日历).
在客户端.
在google developers console上创建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)
并且,要求授权我的Web应用程序可以使用Google Api JS client访问用户的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 developers console创建.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...) })
这里的认证工作正常,
但是calendar.events.list()返回一个’Not Found’错误(谁不是真的很有用……).
如果用户以前允许我的网络应用访问他的日历,
通过服务帐户读取或写入这些日历应该有效吗?
所以我不明白我错过或误解了什么?并需要明确的代码才能继续前进.
希望我的解释足够清楚.
谢谢你的帮助!
解决方法
当用户向您的应用授予权限(使用客户端ID)时,您的应用将能够访问用户的信息,在本例中为日历.
但是,这不是通过服务帐户完成的,而是通过客户端ID完成的.
在您的服务器端代码(云功能)中,您似乎使用服务帐户对Google日历进行身份验证,这意味着您正在访问服务帐户的日历,而不是在Web应用中验证的用户的日历(类似于常规)帐户,服务帐户可以访问驱动器或日历等服务.
除非用户使用服务帐户提供/共享日历,否则您的服务帐户将无权访问用户的日历(类似于将日历共享给其他Gmail帐户).
如果要在服务器端访问该用户的日历,则需要将客户端上的Google身份验证返回的访问令牌和刷新令牌传递到服务器端.然后,您可以使用访问令牌代表用户调用Calendar.