何故、認証済みのGoogle Apps Scriptのコードで再認証が求められるのか?

Google Apps Scriptでコードを書いて初回に必ず求められるスコープの承認作業。基本1度認証を行って許可を与えれば、暫くは求められることはないのですが、半永久的に求められないというものではありません。その為、暫くつかっていないとまた「再度認証を求められる」という事が発生し、時にトリガーなどで実行が出来ずにエラーになったりします。

また、コード編集時にこれまでに承認してこなかったスコープが増えても、改めて承認が必要になったりとわりと鬱陶しいと思われてるようです。今回はこの「スコープの承認」が何故定期的に発生するのか?その仕組をまとめてみました。

あの認証は何なのか?

Google Apps Scriptの認証画面。現在はさらに細かくチェックを入れてから承認をするスタイルとなっており、初回実行時には必ず承認をしてあげる必要があります。同一スクリプトであってもユーザーが異なれば必ず誰でも1回は実行が必要です。仕組みを知らない人はこの画面が出てくるものだから怖くて承認せず、結局スクリプトが実行できずにエラーになるなんて話も聞きます。

これは、このアプリが使ってるメソッドによって例えばメール送信ならば送信の許可、ドライブのファイルの編集ならば編集権限の許可をまとめて求めるもので、様々なスコープと呼ばれるものが存在し、GASがそれらを自動的にそれを判断して求めてくる「OAuth認証」と呼ばれるものになります。

よって、Google Apps Scriptだけでなく、Node.jsでプログラムを作ってGoogle APIを叩くものならば同様に認証を求められ、またGoogle APIだけでなく、Google Cloud側のAPIを使ってる場合も同様に求められる仕組みであるため、許可しないとプログラム実行が停止してしまいます。

ただ、1度承認すれば永久に使えるわけではなくそこには様々なルールと、承認の失効の期間というものが存在している為、定期的に承認実行をする必要性があるのです。

※Google APIだけでなくGoogleアカウントで他のWebサービスにログインするようなケースでも同様の仕組みで認証が求められます。

図:これが現在の認証ダイアログ

ルールと失効までの日数

デフォルトプロジェクト

実は、GASはスプレッドシートでスクリプトエディタを開いた時に、自動的にGoogle Cloud側に「デフォルトプロジェクト」という形で、Client IDなどが作成されています。Google CloudのAPIとサービスの中にある「認証情報」の中にそれらが自動で作られています。

このデフォルトプロジェクトなのですが、ここに1つルールが存在します。

  • 自身が作って自身が実行する場合には、OAuth同意画面のルールが適用されないで、「本番」扱いとなる
  • 自身が作って他人が実行する場合には、OAuth同意画面のルールが内部であっても「テスト」扱いとなる
  • テストの場合には、OAuth認証のトークンの期限は7日間となり、7日間使わなければ7日後にまた認証を求められるようになる。
  • 自身が作って自身が実行の場合は、OAuth認証のトークンの期限は6ヶ月となります。

しかもデフォルトプロジェクトは自動生成でその設定を変更することが出来ません。よってテストではなく「本番」といったステータスに変更することも出来ません。

つまり標準の状態では、他のユーザは使わないままでいると7日でトークンの有効期限が来てしまいます。

図:実はGoogle Cloudにこっそり作られてる

標準プロジェクト

標準プロジェクトとは、Google Cloud側に用意したプロジェクト番号をもって、Google Apps Scriptのプロジェクトを連結する作業をしたものを指します。この作業を行うGoogle Cloud側のプロジェクトとの連結解除は出来なくなるので注意が必要ですが、Google Cloud側のAPIを利用するようなケースやサービスアカウントを使って動かすようなケースでは必須の作業になっています。

Google Cloud側のプロジェクト番号はWelcomeのダッシュボードに記載されている番号で、GAS側ではスクリプトエディタのプロジェクト設定に於いて、Google Cloud Platform(GCP)プロジェクトという場所で連結作業を行えます。

連結をするとデフォルトプロジェクトではなくなり、ルールも代わります

  • 自身も他人もOAuth同意画面において内部となっている場合にはデフォルトでは「本番」ステータスとなります。
  • 外部の場合はテストなのか?本番なのか設定変更をすることができる用になります。
  • 本番のステータスの場合、7日間ではなくOAuth認証のトークンの期限は6ヶ月間となります。

よって6ヶ月使わない状態でいるとデフォルトプロジェクト同様にトークンが失効して、再度認証を求められるという状態になります。

図:GCP側と連結する場合に使う

1アカウント100個まで

1アカウントあたりOAuth認証のリフレッシュトークンを発行できる上限が100プロジェクトまでというのがこちらのドキュメントに記載されています。これ何なのか?というと、アプリは再実行時にリフレッシュトークンというものを使って、トークンを新しく取得しており、これによりトークン失効期限がその日から◯◯日という具合に延長されているのですが、このトークン発行できるプロジェクトを保持できるのが最大100個までというあまり知られていないルールです。

101個目のプロジェクトを作るとどうなるのか?というと一番古いプロジェクトのアクセストークンが自動的にその場で失効し、新たに承認が求められるようになるということです。しかしここで承認すると、次に一番古いものが失効するので100個以上1アカウントでプロジェクトを作ってしまうと、必ずなにかのプロジェクトでは次回実行時に承認を求められてしまうという仕組みです。

再認証が求められる

新しいスコープのメソッドを使った場合

GASのコードでそれまで使っていなかったような新しいスコープの範疇のメソッドを追加してプログラミングをした場合、いざ実行をするとトークンの失効とは無関係に新たなスコープをGASの仕組みが検知して、必ず認証を求めてくるようになります。

よって、開発者は頻繁に新たな領域のコードを書くたびにその認証作業をしないといけないため、かなり煩わしいことになります。ただこの検知は、デフォルトでは自動で行われる為一方ではスコープ指定を手動でやらなくても適切な認証が行えるというメリットもあります。

よって、自身が書くプログラムのスコープがあらかじめ分かっているのであるならば、最初から定義してしまうということも可能で、それがappsscript.jsonです。ここにoauthScopesというブロックでスコープ一覧を定義してしまえば、まだ該当のメソッドが無くても初回の1回でまとめて要求されて許可できるため、煩わしさもなくなります。

Google Cloud側のAPIを使う場合には、appsscript.jsonにて明示的にスコープ要求を書かないと、認証要求されずに403エラーになるケースがあるので基本appsscript.jsonの記述をするのが標準的なやり方になります。

図:手動でスコープ追加をしたケース

GASのスコープ誤認識

必ず発生するわけではない為、再現することが出来ないのですが、時々新たなスコープの領域のメソッドを足したわけでもなければ、トークンが失効するほど使っていないのに「再認証要求」が走るケースがあります。これは、GASのメソッドによるスコープ検知が誤認識して再認証要求を出してしまうケースです。

例えば、これまでxxxx.gsに記述し、ooooo.gsに別のメソッドを記述。このgsファイルの順番を上下入れ替えたり、コード内で関数の位置を変えたりした場合に稀に発生するバグのようなものです。こればかりはどうにもならないので基本はあまり位置の入れ替え等はしないほうが良いでしょう。

しかしこの場合も前述のappsscript.jsonに手動でスコープを定義してる場合には、問題が発生しなくなるのでそこそこ腕がついてスコープ要求される内容がわかっているのであれば、appsscript.jsonに手動で記載してしまうことで煩わしさも誤作動もなくなります。

自分でプロジェクト承認を取り消し

ユーザーがGASの認証を実行や、他のWebサービスへのログイン時にアクセス要求を手動で取り消しをすると、再度同じアプリやWebサービスにログイン時には再認証要求が走ることになります。

この手動で承認取り消しは、Googleアカウント設定上のセキュリティ項目にある「サードパーティ製のアプリとサービス」の所で、個別にキャンセルをすることが可能です。過去に認証許可したけれど怪しいなと思ったり、もう使っていないサービスだから認証取り消しをして、相手サービス側からAPIへのアクセスを遮断する場合に使います。

しかしこれによって承認取り消しをしてるので、過去のアクセストークンの有効期限はその場で失効となるため、また使いたいとなったら当然初回認証時と同じく承認要求されることになります。

図:手動で許可をリジェクト可能

自動で失効期限を延長する方法

ここまでで、一度認証したプログラムが再認証要求される理由が理解できたかと思います。しかし、そうなるとたまにしか使わないようなプログラムは毎回要求されるということになります。デフォルトプロジェクトのままでユーザーが7日以上の間をあけて使うといったケースでも、ユーザは「この間承認したのにまた求められる」と感じるでしょう。

この再認証を求められる状態を延長する手段は、期限前にプログラムを実行するという事によるリフレッシュトークンを使ったトークンの再取得しか無いわけで、第三者が自動化のためにトリガーを使ってるケースでは、7日以上の間をあけると「毎回実行エラーになる」という謎現象にハマるわけです。でも、手動で実行するとちゃんと動く。

この回避法はすでに前述にもありますが

  • デフォルトプロジェクトで運用しないで標準プロジェクトとして運用する(期限がこれで6ヶ月になる)
  • さらに定期的に適当なダミーの関数を用意して、トリガーで定期実行するようにする(これでトークン再取得がなされる)

また、迂回技ですが、直接GASを実行するのではなくウェブアプリにしておき、ユーザにはウェブアプリを使ってもらいその際の実行権限は「作成者の権限で動かす」ようにし、個別にリクエスト要求を求めないようにするのがベターでしょう。これはウェブアプリでしか出来ないことなので、少し手間になりますがアクセストークンの更新作業は作者のみで済むため、ユーザがアプリを実行するたびに承認要求されてきてウンザリということが大分減らすことが可能です。

Google Apps Scriptでウェブアプリケーション作成入門【GAS】

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)