7
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Organization

GASから認証付きのCloud Functionsを実行する。

はじめに

Google Apps Script(以下GAS)からCloud Functions(以下GCF)の認証付きのHTTP関数を呼べたら便利だなあという場面、あると思います。

本記事ではGASから認証付きHTTPトリガーのGCFを実行するための設定、記述方法についてご紹介します。

GCPプロジェクト側の設定

GASのプロジェクトが作成されると初期設定では「デフォルト」というGCPプロジェクトと紐付けられています。
この紐付け先ののGCPプロジェクトをCloud Functionsがデプロイされているプロジェクトへ変更してあげる必要があります。
こちらの項では紐付け先のGCPプロジェクトの設定を行っていきます。

OAuth同意画面の作成

OAuth同意画面とはGASを初回実行したときに表示されるポップアップウィンドウです。
OAuthを利用した認証するときによく出てくるあれです。
スクリーンショット 2021-02-25 21.41.30.png

GCPのコンソールから「APIとサービス」->「OAuth同意画面」で設定を行うことができます。
既に作成されている場合はスキップでOKです。
まだ、作成されていない場合は「内部」あるいは「外部」向けに設定を進めてください。
GASの用途の多くは社内向けかと思いますのでGoogle Workspaceを利用している場合は「内部」でいいかと思います。

ひとまずは必須項目のみ設定しておき、必要に応じてスコープを追加していきましょう。(今回のデモでは特に必要ないです。)

APIを有効化しておく。

続いてGASで利用されるGmail APIやDrive APIをGCPプロジェクト側で有効化しておく必要があります。
「APIとサービス」->「ライブラリ」からそのあたりのAPIを有効化しておきましょう。
スクリーンショット 2021-02-25 21.50.59.png
Google Workspaceというカテゴリがあるのでフィルタをかけると便利です。

お疲れ様でした!
続いてGAS側の設定です。

GAS側の設定

プロジェクトの設定

先述のようにGASプロジェクトに紐付けられているGCPプロジェクトを先程設定したプロジェクトに変更する必要があります。
GASプロジェクトの設定画面から、「プロジェクトの変更」をクリックし、当該プロジェクト番号を貼り付けてください。
プロジェクト番号は、GCPコンソールのダッシュボードで確認できます。
また、後ほどappscript.jsonを編集するため、エディタで表示させておきます。
 スクリーンショット 2021-02-25 21.55.34.png

紐付け先GCPプロジェクトの認証情報画面でOAuthクライアントにGASのものが追加されていたらOKです。
スクリーンショット 2021-02-25 22.24.29.png

appscript.jsonの編集

appscript.jsonでは、GASのランタイムやタイムゾーン、OAuthスコープの設定を行うことができます。
GCFの認証つきHTTPトリガー関数ではエンドユーザの認証にID トークンを利用します。
このIDトークンをGASで取得するためにOAuthスコープを追加する必要があります。

appscript.json
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
      "https://www.googleapis.com/auth/userinfo.profile",
      "https://www.googleapis.com/auth/userinfo.email",
      "https://www.googleapis.com/auth/script.external_request",
      "https://www.googleapis.com/auth/drive"
  ]
}

https://www.googleapis.com/auth/userinfo.profilehttps://www.googleapis.com/auth/userinfo.emailのスコープがIDトークン取得に必要なスコープです。

https://www.googleapis.com/auth/script.external_requestはUrlFetchAppを利用する際に必要となるスコープです。
その他のスコープは必要に応じて追加してください。(スクリプト上のスコープが足りてない場合はその旨がエラーログで表示されます。)

GASでのIDトークン取得に関する公式ドキュメントはこちらとなります。

作ってみよう!

Cloud Functionsをデプロイする。

認証付きのHTTPトリガーで関数を作っていきます。
スクリーンショット 2021-02-25 22.29.11.png
ソースコードは簡単のためデフォルトのものにしておきます。

index.js
/* ランタイムはNode.js 14(ベータ)です。 */
exports.helloWorld = (req, res) => {
  let message = req.query.message || req.body.message || 'Hello World!';
  res.status(200).send(message);
};

ソースが書けたらデプロイしましょう。
既存の関数を使用する場合もOAuthクライアントの情報を反映させるために再度デプロイする必要がありますので注意してください!!

保護する関数を再度デプロイします。これにより、関数に正しいクライアント ID が設定されます。
https://cloud.google.com/functions/docs/securing/authenticating?hl=ja#google_sign-in

GASを書いていく

先述のようにGASでIDトークンを取得するには次の関数を使用します。

const idToken = ScriptApp.getIdentityToken()

上記で得られたIDトークンをHTTPリクエストに含めていきます。

コード.gs
function myFunction() {
  const url = "https://xxxxxx.cloudfunctions.net/xxxxx"
  const res = UrlFetchApp.fetch(url, {
    headers: {
      Authorization: `Bearer ${ScriptApp.getIdentityToken()}`
    }
  })
  console.log(res.getContentText()) // Hello World!
}

お疲れ様でした!
正しく設定されていたら無事、認証付きのHTTPトリガーのGCFにアクセスできるかと思います。

最後に

Cloud Functionsの認証が思いのほか厄介だったのでまとめてみました。
GCP側でOAuth同意画面を用意したり、APIを有効化したりとGASの外での設定が多いため、
GASでエラーを吐くようであれば設定を確認してみてください。

紐付け先のGCPプロジェクトを変更して個人的にハマったのが、GASで発生した謎のエラー
“We're sorry, a server error occurred. Please wait a bit and try again”

原因はGCP側でDrive APIが有効化されてなかったことでした。

皆様もよきGAS&GCFハックを!!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
7
Help us understand the problem. What are the problem?