使用 Firebase Auth 访问 Google 日历 API

Using Firebase Auth to access the Google Calendar API

我正在使用 AngularJS、Firebase (SDK v3) 和 Google 日历 API 构建 Web 应用程序。我正在使用 Google OAuth 对用户进行身份验证。我的目的是能够从 Firebase 中的数据库节点创建日历事件。到目前为止,我已经设法请求访问日历范围:

_authProvider = new firebase.auth.GoogleAuthProvider();
// Get permission to manage Calendar
_authProvider.addScope("https://www.googleapis.com/auth/calendar");
_fbAuthObject.signInWithRedirect(_authProvider);

我正在使用重定向流程进行身份验证,因此身份验证重定向可用:

_fbAuthObject.getRedirectResult()
    .then(function _readToken(result) {
      if (result.credential) {
        _googleToken = result.credential.accessToken;
        var authHeader = 'Bearer '+ _googleToken;

        // Just a test call to the api, returns 200 OK 
        $http({
          method: 'GET',
          headers: {
            'Authorization': authHeader
          },
          url: 'https://www.googleapis.com/calendar/v3/users/me/calendarList/primary'
        })
          .then(function success(response) {
            console.log('Cal response', response);
          },
          function error(response) {
            console.log('Error', response);
          });

但是,似乎在初始登录之外无法通过 Firebase SDK 获取 Google 访问令牌。似乎只能访问 Firebase JWT 令牌,不能用于日历 API。我可以存储访问令牌,但这不能解决刷新令牌等问题。有什么方法可以使用 Firebase SDK 获取当前的 Google 访问令牌,如果没有,还有哪些其他解决方案无需对用户进行两次身份验证的问题?

更新 1:

似乎 someone else has struggled with similar problems with Facebook authentication. On that question there was a link to the Firebase documentation 指出 Firebase 身份验证不再保留访问令牌。那么我该如何处理令牌刷新呢?真的没有答案吗?

更新 2:

因此,我联系了 Firebase 支持部门,提出了关于此问题的功能请求,他们给了我以下答复:

Thanks for taking your time to write us.

I've got your point here, this is indeed a good suggestion. We're definitely aware that many users, such as yourself, would like OAuth feature that will access token upon refresh. We're exploring potential solutions, but I cannot guarantee if this will be available anytime soon. We'll keep your feedback in consideration moving forward though. Continuous improvement is very important for our community, so thanks for bringing this up!

Keep an eye out on our release notes for any further updates.

因此,目前似乎无法通过 Firebase SDK 获得访问令牌。我仍在努力寻找解决方法,所以如果有人对有效的解决方案有想法,我很乐意听取他们的意见。当然,如果我自己找到可行的解决方案,我会把它贴在这里。

我终于通过使用 Google APIs JavaScript 客户端处理 Firebase 外部的身份验证解决了这个问题。此解决方案需要将 Google 身份验证客户端包括为 documented here. Manually handling the Firebase sign-in flow is documented here.

gapi.auth2.getAuthInstance().signIn()
    .then(function _firebaseSignIn(googleUser) {
      var unsubscribe = firebase.auth().onAuthStateChanged(function(firebaseUser) {
        unsubscribe();
        // Check if we are already signed-in Firebase with the correct user.
        if (!_isUserEqual(googleUser, firebaseUser)) {
          // Build Firebase credential with the Google ID token.
          var credential = firebase.auth.GoogleAuthProvider.credential(
            googleUser.getAuthResponse().id_token);

          // Sign in with credential from the Google user.
          return firebase.auth().signInWithCredential(credential)
            .then(function(result) {
              // other stuff...
            });

_isUserEqual 函数:

function _isUserEqual(googleUser, firebaseUser) {
  if (firebaseUser) {
    var providerData = firebaseUser.providerData;
    for (var i = 0; i < providerData.length; i++) {
      if (providerData[i].providerId === firebase.auth.GoogleAuthProvider.PROVIDER_ID &&
        providerData[i].uid === googleUser.getBasicProfile().getId()) {
        // We don't need to reauth the Firebase connection.
        return true;
      }
    }
  }
  return false;
}

现在我可以像这样引用访问令牌:

var user = gapi.auth2.getAuthInstance().currentUser.get();
return user.getAuthResponse().access_token;

这对我来说仍然不是理想的解决方案,但它现在可以使用,而且我能够向 Firebase 和日历进行身份验证 API。