Google Apps Script内部のリフレッシュトークンは、1週間後も有効か?(7日認証切れ問題)
前回の投稿では、Google Apps Script(以下 GAS)のScriptApp.getOAuthToken()を実行した際、「内部的にリフレッシュトークンが保持され、それを使ってアクセストークンを自動更新しているのではないか?」という考察を行いました。
Google Apps ScriptのOAuth認証URLとリフレッシュトークン有効期限を調査
通常、GCP(Google Cloud Platform)のOAuth設定において、アプリを「外部(External)」かつ「テスト(Testing)」ステータスで公開した場合、セキュリティ上の制約によりリフレッシュトークンは7日間で無効化(失効)されます。
そこで今回は、GASが内部で管理しているリフレッシュトークンも、GCPの仕様同様に「1週間経過すると無効になってしまい、アクセストークンが取得できなくなるのでは?」という点を検証しました。
結論:GAS管理下のリフレッシュトークンは無効化されない
1週間経過後に改めて検証を行った結果、リフレッシュトークンは無効化されておらず、正常に新しいアクセストークンが取得できることを確認しました。
これにより、GAS標準のトークン管理メカニズムは、GCPの「テスト」ステータスにおける「リフレッシュトークンの有効期限7日」という制約の影響を受けない(あるいはGASプラットフォーム側で特別に維持されている)ことがわかります。
なぜ、テストモードの7日制限を受けないのか?
この挙動について、公式ドキュメントに「GASは例外である」と明記された箇所は見当たりません。
しかし、GCPとGASそれぞれの仕様(および今回の検証結果)を照らし合わせると、以下のような仕組みであると考えられます。
トークン管理の仕組みと仕様
-
一般的なOAuthアプリ:開発者がリフレッシュトークンをDB等に保存・管理する。
- GCPの制約(7日制限)が直接適用される。
-
GAS(ScriptApp):GASの実行基盤(ランタイム)が、ユーザーに代わってトークンを内部管理する。
- Googleの内部システムとしてトークンの維持・更新が行われるため、テストモードの制約を直接受けない。
つまり、ユーザーからは「テスト」状態に見えていても、裏側ではGASというGoogleファーストパーティの特権的な仕組みによって、トークンの有効性が維持されていると考えられます。
出典情報
一般的なOAuthアプリ
The only exception to this behavior is if your app requests a subset of the following: name, email address, and user profile (through the userinfo.email, userinfo.profile, openid scopes or their OpenID Connect equivalents).
For such requests, your users do not need to be in the trusted user list, they will not see a warning message, and their authorizations will not expire after 7 days.
If your app uses Sign in with Google to authenticate users then this exception also applies.
If your app requests any other OAuth scopes, then this exception does not apply.
この動作の唯一の例外は、アプリが以下のサブセット(名前、メールアドレス、ユーザープロフィール)をリクエストする場合です(userinfo.email、userinfo.profile、openid スコープ、またはそれらに相当する OpenID Connect スコープ経由)。
このようなリクエストの場合、ユーザーは信頼できるユーザーリストに登録されている必要はなく、警告メッセージは表示されず、承認は 7 日後に期限切れになることはありません。
アプリがユーザー認証に Google でログインを使用している場合も、この例外が適用されます。
アプリがその他の OAuth スコープをリクエストしている場合、この例外は適用されません。
GAS(ScriptApp)
有効なユーザーの OAuth 2.0 アクセス トークンを取得します。
スクリプトの OAuth スコープが、通常は独自の OAuth フローを必要とする別の Google API(Google Picker など)を承認するのに十分な場合、スクリプトはこのトークンを渡すことで、2 回目の承認プロンプトをバイパスできます。
トークンは一定時間(少なくとも数分)後に期限切れになります。
スクリプトは認証の失敗を処理し、必要に応じてこのメソッドを呼び出して新しいトークンを取得する必要があります。
このメソッドから返されるトークンには、スクリプトが現在必要とするスコープのみが含まれます。
以前に承認されたものの、スクリプトで使用されなくなったスコープは、返されるトークンに含まれません。
スクリプト自体が必要とするもの以外に OAuth スコープが必要な場合は、スクリプトのマニフェスト ファイルで指定できます。
どのようなケースで活用できるか
この仕様は、特に自分専用のツールやミニアプリを作成する際に強力な選択肢となります。
通常、無料のGoogleアカウント(Gmail.com)でOAuthクライアントを作成する場合、User Typeは「外部」しか選択できず、正式公開前の「テスト」状態では「7日ごとにリフレッシュトークンが切れ、再認証が必要になる」という壁にぶつかります。
しかし、GASのScriptApp.getOAuthToken()を利用すれば、この「7日認証切れ問題」を回避しつつ、手軽にGoogle APIを利用した開発が可能になります。

