LoginSignup
11
7

More than 1 year has passed since last update.

GoogleスプレッドシートAPIをサービスアカウント認証方式でNode.jsから利用する

Last updated at Posted at 2022-09-26

Google系のAPIはOAuth認証、サービスアカウント、APIキーの利用の3パターンあると認識してますが、簡単な読み書きくらいのやりとりだとサービスアカウント利用は手ごろです。

参考
Google DriveのAPIをサービスアカウント認証方式でNode.jsから利用するメモ

前提

以下ができてる前提になります。

  • Google SheetsのAPIを許可してサービスアカウント作成
  • 作成したサービスアカウントを対象のシートに権限付与
  • サービスアカウントの鍵ファイルをJSON形式で取得

鍵ファイルをDLすると以下のような雰囲気の中身となります。

{
	"type": "service_account",
	"project_id": "xxxxxxxx",
	"private_key_id": "xxxxx",
	"private_key": "-----BEGIN PRIVATE KEY----○-----END PRIVATE KEY-----\n",
	"client_email": "hogehoge@hogehoge.iam.gserviceaccount.com",
	"client_id": "1111111111111111111111111111",
	"auth_uri": "https://accounts.google.com/o/oauth2/auth",
	"token_uri": "https://oauth2.googleapis.com/token",
	"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
	"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/xxxxxxxxxxxxx"
}

↑はあくまでもサンプルです。

とりあえず情報を取得するコピペサンプル

この場合必要ライブラリはgoogleapisのみです。

$ npm i googleapis

以下のコードで、サービスアカウントを追加してアクセスを許可したシートのID範囲を変更しつつ、鍵ファイルをkeyfile.jsonとして同一フォルダに置いておけば動くと思います。

ss.js
'use strict';

const {google} = require('googleapis');

const KEYFILE_NAME = `keyfile.json`;
const KEYFILE_PATH = `./${KEYFILE_NAME}`;

const main = async () => {

    console.log(`--Google SpreadSheet認証`);
    let sheets = {};
    try {
        const auth = new google.auth.GoogleAuth({
            keyFile: KEYFILE_PATH,
            scopes: ['https://www.googleapis.com/auth/spreadsheets'],
        });
        sheets = google.sheets({version: 'v4', auth});
        console.log(`認証done--`);
    } catch (error) {
        console.log(error);
    }
    
    console.log(`--sheetアクセス`);
    try {
        const res = await sheets.spreadsheets.values.get({
            spreadsheetId: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`, //シートのIDを指定
            range: `Form1!A:H`, //取得する範囲を指定
        });
        console.log(res.data);
    } catch (error) {
        console.log(error);
    }

}

main();

これで実行すると以下のように情報が取れると思います。

$ node ss.js
--Google SpreadSheet認証
認証done--
--sheetアクセス
--sheetアクセス
{
  range: 'Form1!A1:H104',
  majorDimension: 'ROWS',
  values: [
    [
      'hoge',
      'お名前',
      '所属',
      'GitHubのマイページURL',
      'GitHubに登録したメールアドレス',
      'ステータス',
      '追加team',
      '担任チェック'
    ],

・・・省略

CIで動かしたいver

CIで動かす時にkeyfileを直接GitHubなどに載せるのはしたくないので環境変数に設定したいです。

ただ以下のようにGoogleAuthの関数がKeyFileの指定をしてくるので(これ別のオプションありますかね...?)

const auth = new google.auth.GoogleAuth({
            keyFile: KEYFILE_PATH,
            scopes: ['https://www.googleapis.com/auth/spreadsheets'],
        });

環境変数から情報取得してファイルに書き出し -> 認証 -> 1番最後に消すという処理も加えてみました。

手元でも試したいのでdotenvも追加してます。

npm i dotenv

ローカルだと.envファイルに詰め込みつつ

.env
GOOGLE_PRIVATE_KEY='{ "type": "service_account", ・・・省略
SHEET_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

実行する際にfs.writeFileSyncでファイルを作っています。

'use strict';

const {google} = require('googleapis');

const fs = require('fs');

require('dotenv').config();

const KEYFILE_NAME = `keyfile.json`;
const KEYFILE_PATH = `./${KEYFILE_NAME}`;

const main = async () => {
    try {
        console.log(`--keyfile作成`);
        fs.writeFileSync(KEYFILE_NAME, process.env.GOOGLE_PRIVATE_KEY);
        console.log(`作成done--`);
    } catch (error) {
        console.log(error);
    }

    console.log(`--Google SpreadSheet認証`);
    let sheets = {};
    try {
        const auth = new google.auth.GoogleAuth({
            keyFile: KEYFILE_PATH,
            scopes: ['https://www.googleapis.com/auth/spreadsheets'],
        });
        sheets = google.sheets({version: 'v4', auth});
        console.log(`認証done--`);
    } catch (error) {
        console.log(error);
    }
    
    console.log(`--sheetアクセス`);
    try {
        const res = await sheets.spreadsheets.values.get({
            spreadsheetId: process.env.SHEET_ID,
            range: `Form1!A:H`,
        });
        console.log(res.data);

    } catch (error) {
        console.log(error);
    }

    console.log('---Keyファイル削除');
    try {
        fs.unlinkSync(KEYFILE_PATH);
        console.log('削除しました。--');
        return;
    } catch (error) {
        throw error;
    }
}

main();

これでCIでも動くはず...だったんですが、CircleCIだと何故かうまくいかずGitHub Actionsではうまくいきました。ファイルを作成して書き込みあたりの何かの不具合があるのかも...?

11
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7