NodeJS Firestore身份验证-权限被拒绝

时间:2018-08-14 16:16:50

标签: node.js firebase firebase-authentication google-cloud-firestore

我正在尝试创建一个客户端脚本,该脚本允许某人登录其Google帐户,然后在他们通过身份验证后访问Firestore数据库。使用firebase.auth登录后,除某些原因外,其他所有内容都可以正常工作,它不会将这些数据传递给firebase.firestore来表明它们已通过身份验证。

这是我正在使用的脚本,唯一失败的部分是当我尝试添加到Firestore集合中时。

const firebase = require ("firebase/app");
require("firebase/auth");
require("firebase/firestore");

const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
const util = require('util')

var config = {
    **HIDDEN**
};
firebase.initializeApp(config);

const SCOPES = ['email','profile'];
const TOKEN_PATH = 'token.json';

fs.readFile('credentials.json', (err, content) => {
  if (err) return console.log('Error loading client secret file:', err);
  // Authorize a client with credentials, then call the Gmail API.
  authorize(JSON.parse(content), listLabels);
});

function authorize(credentials, callback) {
  const {client_secret, client_id, redirect_uris} = credentials.installed;
  const oAuth2Client = new google.auth.OAuth2(
      client_id, client_secret, redirect_uris[0]);

  // Check if we have previously stored a token.
  fs.readFile(TOKEN_PATH, (err, token) => {
    if (err) return getNewToken(oAuth2Client, callback);
    oAuth2Client.setCredentials(JSON.parse(token));
    callback(oAuth2Client);
  });
}

function getNewToken(oAuth2Client, callback) {
  const authUrl = oAuth2Client.generateAuthUrl({
    access_type: 'offline',
    scope: SCOPES,
  });
  console.log('Authorize this app by visiting this url:', authUrl);
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  rl.question('Enter the code from that page here: ', (code) => {
    rl.close();
    oAuth2Client.getToken(code, (err, token) => {
      if (err) return console.error('Error retrieving access token', err);
      oAuth2Client.setCredentials(token);
      // Store the token to disk for later program executions
      fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
        if (err) return console.error(err);
        console.log('Token stored to', TOKEN_PATH);
      });
      callback(oAuth2Client);
    });
  });
}

function listLabels(auth) {
    var credential = firebase.auth.GoogleAuthProvider.credential(auth.credentials.id_token);
    firebase.auth().signInAndRetrieveDataWithCredential(credential).catch(function(error) {
        var errorCode = error.code;
        var errorMessage = error.message;
        var email = error.email;
        var credential = error.credential;

        console.log(errorCode);
        console.log(errorMessage);
    });

    var firestore = firebase.firestore();
    firestore.settings({
        timestampsInSnapshots: true
    });

    firestore.collection("users").add({
        test: "Hello"
    });

    firebase.auth().signOut();
}

下面是我对数据库的规则,如果我将其更改为if true;,则可以正常工作。但是我想确保只有经过身份验证的用户才能访问该数据库。

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

1 个答案:

答案 0 :(得分:1)

signInAndRetrieveDataWithCredential方法返回一个Promise,而您在访问Firestore上的数据之前不必等待它完成,因此可能是导致问题的原因。我相信这可能有效:

function listLabels(auth) {
    var credential = firebase.auth.GoogleAuthProvider.credential(auth.credentials.id_token);
    firebase.auth().signInAndRetrieveDataWithCredential(credential)
        .then(user => {    
            var firestore = firebase.firestore();
            firestore.settings({
                timestampsInSnapshots: true
            });

            firestore.collection("users").add({
                test: "Hello"
            });

            firebase.auth().signOut();
        })
        .catch(function (error) {
            var errorCode = error.code;
            var errorMessage = error.message;
            var email = error.email;
            var credential = error.credential;

            console.log(errorCode);
            console.log(errorMessage);
        });
}