【问题标题】:Google-api-nodejs-client: Using service account to call directory api returns invalid inputsGoogle-api-nodejs-client:使用服务帐户调用目录 api 返回无效输入
【发布时间】:2020-08-27 03:46:19
【问题描述】:

我创建了一个服务帐户并启用了域范围的委派。我已经启用了 admin sdk directory api。我正在关注列出所有用户的基本example。在创建服务帐户时,我下载了一个文件。我对this 文档的理解是我需要将凭证文件传递给auth 客户端。但是官方example并没有说明如何将文件实际传递给authClient。我试图创建这样的请求:

    const credentials = await JSON.parse(fs.readFileSync("cred.json"));
    const auth = new google.auth.GoogleAuth({
        credentials: credentials,
        scopes: ["https://www.googleapis.com/auth/admin.directory.user"],
    });

    const authClient = await auth.getClient();
    const { data } = await google
        .admin({ version: "directory_v1", auth: authClient })
        .users.list({
            customer: "my_customer",
        });

但是这个请求返回Invalid Inputs。我似乎找不到有关此主题的任何示例或解释。它还指出我必须冒充用户。但是文档没有显示将用户电子邮件放在哪里? 任何人都可以分享他们如何处理这个问题的经验吗?任何示例代码、文档或解释都会非常有用。

【问题讨论】:

    标签: node.js google-api service-accounts google-api-nodejs-client


    【解决方案1】:

    阅读您链接的最后一个示例,您似乎没有正确验证:

    // Load client secrets from a local file.
    const credentials = await JSON.parse(fs.readFileSync("cred.json"));
    
    // Get authorization using your credentials.
    authorize(credentials, listUsers);
    
    
    /**
     * Create an OAuth2 client with the given credentials, and then execute the
     * given callback function.
     *
     * @param {Object} credentials The authorization client credentials.
     * @param {function} callback The callback to call with the authorized client.
     */
    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]);
    
      return getNewToken(oauth2Client, callback);
    }
    
    /**
     * Get new token after prompting for user authorization, and then
     * execute the given callback with the authorized OAuth2 client.
     *
     * @param {google.auth.OAuth2} oauth2Client The OAuth2 client to get token for.
     * @param {getEventsCallback} callback The callback to call with the authorized
     *     client.
     */
    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.credentials = token;
          callback(oauth2Client);
        });
      });
    }
    
    
    /**
     * Lists users in the domain.
     *
     * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
     */
    async function listUsers(auth) {
      const service = google.admin({version: 'directory_v1', auth});
      const {data} = await service.users.list({
        customer: 'my_customer'
        });
    }
    
    

    正如您在函数getNewToken 中看到的那样,您实际上是通过浏览器使用用户登录的。

    我从official example 的给定页面简化了代码。使用此代码,您每次启动应用程序时都需要通过浏览器登录,但如果您查看官方示例,有一种方法可以存储通过 OAuth2 接收到的令牌,这样它就不会总是要求身份验证。

    【讨论】:

    • 对不起。您解释的示例不适用于服务帐户。服务帐户将在没有他人干预的情况下冒充他人。并且文档上的示例不要提及与此相关的任何内容。不过还是谢谢。
    • 此外,我仍然必须至少通过浏览器初始登录一次。这与我正在寻找的东西背道而驰。
    • 显然是 admin sdk only accepts authorization with OAuth2。不过,您可以做的是在您第一次通过浏览器登录后保存令牌。然后在重新启动应用程序时加载它。
    • 或者从技术上讲,您可以尝试在 Node.js 中重新创建 this example。但是 Node 库可能不接受它作为验证后端的可能方式。
    • 真的。它没有。我必须用 Python 来实现它。谢谢您的帮助。 Nodejs api 的一些文档还不够完善。
    猜你喜欢
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    • 2012-10-26
    • 2019-11-06
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 2019-01-23
    相关资源
    最近更新 更多