はじめに
2020年10月に G Suite が Google Workspace にリブランドされました。
それとは全く関係ないですが Google Classroom や Google Chat などの Google Apis を Node.js 用クライアントである googleapis を使って呼び出す際に、サービスアカウントに対してドメイン全体の委任を行い OAuth 認証を行う必要があったのですが、情報を見つけるのに大分彷徨ってしまったり、見つけたコードの記法が少々古かったり、ポイントとなる subject
の指定方法がやや不適切だったりしたので備忘を兼ねてコードを残しておきます。
認証コード
一応 googleapis のバージョンは 67.0.0 です。古いバージョン(39.2.0とか)でも動きます。
const { google } = require('googleapis');
const credentials = require('./credentials.json'); // サービスアカウント秘密鍵jsonファイル
// ドメイン全体の委任で承認されている OAuth スコープの中から必要な分だけ指定する
const scopes = [
'https://www.googleapis.com/auth/classroom.courses.readonly'
];
// API 呼出し主体となるアカウントを指定。無指定だとパーミッションエラーになる
const clientOptions = { subject: 'great-teacher@my-domain.com' };
async function main() {
const auth = await google.auth.getClient({ credentials, scopes, clientOptions });
const classroom = google.classroom({ version: 'v1', auth });
// api 単位ではなくグローバルオプションとして認証情報をセットする場合は下記のようにする
// const classroom = google.classroom({ version: 'v1' });
// google.options({ auth });
const response = await classroom.courses.list();
console.log(JSON.stringify(response));
}
main().catch(err => {
console.error(err);
process.exit(1);
});
ポイント
getClient のパラメーターとして subject
を指定した clientOptions
を渡す点が重要です。
これを指定しないと 403 エラー (The caller does not have permission
) が返ってきます。
逆に指定した場合はそのアカウントで認証して API を呼び出した場合と同じ結果が返ってきます。
例えば Classroom において教師A が課題1~10、教師B が課題11~20 を作成していた場合、
subject
に教師A のアカウントを指定して courses.courseWork.list()
を実行すれば課題1~10が、
教師B のアカウントを指定して実行すれば課題11~20 が返ってきます。
また、ここでは require
を使って秘密鍵 Json ファイルをオブジェクトとして読み込んで credentials
パラメーターに渡していますが、下記のようにファイルパスを keyFile
パラメーターに渡しても良いです。
const auth = await google.auth.getClient({ keyFile: './credentials.json', scopes, clientOptions });
付録:サービスアカウント作成とドメイン全体の委任
一応この記事だけ見れば良いようにサービスアカウント作成と、そのアカウントに対するドメイン全体の委任の手順を記載しておきます。ドメイン全体の委任についてはGoogle Workspaceの管理者しか実施できず、説明するためのスクショを撮るのもままならなかったりしますので。
OAuth 同意画面の設定
API とサービス
> OAuth 同意画面
ここで設定したアプリ名が Google 管理コンソールでドメイン全体の委任を設定した際に表示されます。
OAuth 同意画面 の設定手順
サービスアカウントの準備
API とサービス
> 認証情報
サービスアカウントの準備手順
サービスアカウント作成
+ 認証情報の作成
から サービス アカウント
を選択。
下記のとおり設定して「完了」
- サービス アカウント名:適当に(ここでは domain-delegation)
- サービス アカウントID:自動設定
- サービス アカウントの説明:空ないし任意の説明文
ドメイン全体の委任を有効化
ドメイン全体の委任の表示
をクリックして展開。
G Suite ドメイン全体の委任を有効にする
にチェックを入れて「保存」
これにより「OAuth 2.0 クライアント ID」が表示されたことを確認し、再度サービスアカウントの編集ボタンをクリック。
鍵を追加
プルダウンから 新しい鍵を作成
をクリック。
キーのタイプとして「JSON」を選択して「作成」し、秘密鍵Jsonファイルをダウンロード。
このファイルがソースコード上で require('./credentials.json')
により取り込んでいた json ファイル。
ドメイン全体の委任の承認
Google 管理コンソール > セキュリティ
ドメイン全体の委任の承認手順
おわりに
探し方が悪いのかサービスアカウント認証関連の公式ドキュメントを探しても subject
を指定しなきゃダメという情報を見つけられず、参考にさせて頂いた記事を見てようやく認証を通すことができました。
一応 subject
の指定方法は適切な形になっているはずですし、async/await 版でのサンプルにもなっていると思いますので参考になれば。