node.js - 通过服务帐户访问Google Drive : Error: Login Required

标签 node.js google-drive-api google-oauth service-accounts

const {google} = require('googleapis');
let drive = google.drive('v3');

exports.handler = async (req, res) => {
    res.set('Access-Control-Allow-Origin', '*')
      .set('Access-Control-Allow-Methods', 'POST')
    .status(200);
  var privatekey 
  var jwtClient 
  await global.admin.database().ref(`g_drive_token/OfficServiceAccount`).once('value').then((doc)=> {
    privatekey = doc.val()
    jwtClient = new google.auth.JWT(
      privatekey.client_email,
      null,
      privatekey.private_key,
      ['https://www.googleapis.com/auth/drive.file'],
      null);
      console.log(JSON.stringify(jwtClient))   
      authWithServicePrivateKey(jwtClient)
      return "null"
    }) .catch((error)=> {            
    console.log('Error fetching user data:+', error);
      return "null"
  }) 


function authWithServicePrivateKey(jwtClient){
  //authenticate request
jwtClient.authorize(function (err, tokens) {
    if (err) {
      console.log("Could not connect***!"+err);
      return;
    } else {
      console.log("Successfully connected!");
      console.log('token******'+JSON.stringify(tokens))
      listFolderInGoogleDrive()
      CreateFolderInGoogleDrive()
    }
   });
}


//Google Drive API
function listFolderInGoogleDrive() {
    console.log('listFolderInGoogleDrive() was called')
    drive.files.list({
        auth: jwtClient,
        pageSize: 10,
        fields: 'nextPageToken, files(id, name)',
      }, (err, res) => {
        if (err) return console.log('The API returned an error: ' + err);
        console.log(JSON.stringify(res.data))
        console.log(JSON.stringify(res.data.files))
        const files = res.data.files;
        if (files.length) {
          console.log('Files:');
          files.map((file) => {
            console.log(`${file.name} (${file.id})`);
          });
        } else {
          console.log('No files found.');
        }
      });
    }

    function  CreateFolderInGoogleDrive() {
        console.log('CreateFolderInGoogleDrive() was called')
        var fileMetadata = {
            auth: jwtClient,
            'name': 'OfficService',
            'mimeType': 'application/vnd.google-apps.folder',
            'parents':['12CCq1GGoTyDW_Ox09TZf5BDgaPAjB0AR']
          };
          drive.files.create({
            resource: fileMetadata,
            fields: 'id'
          },(err, file)=> {
            if (err) {
              // Handle error
              console.error(err);
            } else {
             console.log('***parent****'+ file.data.id) 
           
            }
          });
        }

注意:云端硬盘文件夹“12CCq1GGoTyDW_Ox09TZf5BDgaPAjB0AR”已与服务帐户电子邮件 ID 共享。

以下是控制台日志的一些结果,反射(reflect)了失败的位置。

token******{"access_token":"************","token_type":"承载","expiry_date":1593865140000,"refresh_token":"jwt-placeholder “}

listFolderInGoogleDrive() 被调用

调用了 CreateFolderInGoogleDrive()

错误:需要登录

我想,我没有使用 token 进行身份验证。请帮助我使用 Node.js 代码来使用此 token 来验证服务帐户。

最佳答案

我想修改以下修改。

修改点:

  • exports.handler = async (req, res) => {} ,最后}未使用。所以你的脚本不完整。请小心这一点。
    • 从你的问题来看,我认为这可能是脚本的错误复制。
  • 在您的脚本中,jwtClient未在listFolderInGoogleDrive()处使用和CreateFolderInGoogleDrive() 。我认为这可能是您出现问题的原因。
  • CreateFolderInGoogleDrive() , auth: jwtClient需要用在 {resource: fileMetadata, fields: "id"} 的对象中。
    • 但在这种情况下,我建议添加 jwtClientdrive喜欢 google.drive({ version: "v3", auth: jwtClient }) .

当以上几点反射(reflect)到您的脚本中时,它会变成如下所示。在这种情况下,authWithServicePrivateKey的功能, listFolderInGoogleDriveCreateFolderInGoogleDrive已修改。

修改后的脚本:

function authWithServicePrivateKey(jwtClient) {
  // Modified
  jwtClient.authorize(function (err) {
    if (err) {
      console.log("Could not connect***!" + err);
      return;
    }
  });
  drive = google.drive({ version: "v3", auth: jwtClient }); // Added
  listFolderInGoogleDrive();
  CreateFolderInGoogleDrive();
}

//Google Drive API
function listFolderInGoogleDrive() {
  console.log("listFolderInGoogleDrive() was called");
  drive.files.list(
    {
      //   auth: jwtClient,  // Removed
      pageSize: 10,
      fields: "nextPageToken, files(id, name)",
    },
    (err, res) => {
      if (err) return console.log("The API returned an error: " + err);
      console.log(JSON.stringify(res.data));
      console.log(JSON.stringify(res.data.files));
      const files = res.data.files;
      if (files.length) {
        console.log("Files:");
        files.map((file) => {
          console.log(`${file.name} (${file.id})`);
        });
      } else {
        console.log("No files found.");
      }
    }
  );
}

function CreateFolderInGoogleDrive() {
  console.log("CreateFolderInGoogleDrive() was called");
  var fileMetadata = {
    // auth: jwtClient,  // Removed
    name: "OfficService",
    mimeType: "application/vnd.google-apps.folder",
    parents: ['12CCq1GGoTyDW_Ox09TZf5BDgaPAjB0AR'],
  };
  drive.files.create(
    {
      resource: fileMetadata,
      fields: "id",
    },
    (err, file) => {
      if (err) {
        // Handle error
        console.error(err);
      } else {
        console.log("***parent****" + file.data.id);
      }
    }
  );
}

注意:

  • 在此修改中,假设您已经能够通过您的服务帐户使用 Drive API 获取和输入 Google 云端硬盘的值。请小心这一点。

添加:

当您想要检索您手动创建的文件的文件列表时,请修改范围如下。

来自:

['https://www.googleapis.com/auth/drive.file'],

致:

['https://www.googleapis.com/auth/drive'],
  • 关于https://www.googleapis.com/auth/drive.file的范围, the official document说如下。

    Per-file access to files created or opened by the app. File authorization is granted on a per-user basis and is revoked when the user deauthorizes the app.

而且,您只想检索12CCq1GGoTyDW_Ox09TZf5BDgaPAjB0AR的共享文件夹的文件列表。 ,请修改如下。

来自:

drive.files.list({
    auth: jwtClient,
    pageSize: 10,
    fields: 'nextPageToken, files(id, name)',
  }, (err, res) => {

致:

drive.files.list({
    auth: jwtClient,
    pageSize: 10,
    fields: 'nextPageToken, files(id, name)',
    q: "'12CCq1GGoTyDW_Ox09TZf5BDgaPAjB0AR' in parents",  // Added
  }, (err, res) => {

关于node.js - 通过服务帐户访问Google Drive : Error: Login Required,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62735018/

相关文章:

json - Powershell ConvertTo-JSON 返回 "nested"对象

javascript - React - 开发和生产中的环境变量

android - 自动使用 Google Eclipse Plugin 和手动添加 .jar 文件之间包含 Drive API 库的不同之处

flutter - 如何在 flutter 应用程序中使用 google Drive api 创建文件夹?

PHP - 带有 Google Gmail OAuth2 API 的 ListMessages

java - 谷歌应用引擎中的 Json

php - Node.js 与 Laravel 4.2

google-drive-api - 阻止 Google Drive File Stream 立即同步已删除的文件

javascript - Google oauth2 web 应用程序与 javascript 应用程序

node.js - 如何从 docker 连接到在 aws ec2 主机 (linux) 上运行的 MongoDB