実務メモ / 設定ガイド

Google OAuth 同意画面を本番公開する

個人開発アプリの Google スプレッドシート連携を、開発者本人以外も使える状態にするまでの記録。手続きそのものより、「ホームページのウェブサイトが登録されていません」で止まったときの切り分けに紙面を割いています。

対象Google の API(Sheets / Drive / Gmail など)をユーザーのアカウントで叩くアプリを、一般に配布したい個人開発者
きっかけMyDictly(単語帳アプリ)のスプレッドシート連携が、テストユーザーに登録した数人しか使えなかった
使ったスコープhttps://www.googleapis.com/auth/spreadsheets(機微スコープ)
時点2026-08-22 時点の Google Auth Platform の画面にもとづく
最終更新2026-08-22
関連ノートApp Store にリリースする手順 / MyDictly 開発ノート
注意Google のコンソールは画面名も導線も頻繁に変わります(OAuth 同意画面 → Google Auth Platform への改称もそのひとつ)。最終的な判断は実際の表示に従ってください

TL;DR

ひとことで

公開ステータスが「テスト」のままだと、登録したテストユーザー 100 人しか使えません。しかも認可が 7 日で失効するので、週に一度ログインし直しを強いることになります。一般配布するなら本番公開は必須です。

機微スコープを使うなら、本番公開だけでは足りず Google の審査が要ります。審査に必要なのは、ドメインの所有権確認・ホームページ・プライバシーポリシー・スコープの正当化・デモ動画。技術的な難所はゼロで、詰まるのは所有権確認だけでした。

そして所有権確認で丸一日溶かした原因は、レジストラと DNS ホスティングを混同していたことでした。ドメインはお名前.com で買っていても、ネームサーバーが AWS に向いていれば、TXT レコードは Route 53 に入れないと存在しないことになります。

Problem

テストのままだと、そもそも配れない

Google Auth Platform の「対象」ページには公開ステータスという設定があり、ここが テスト / 本番 の 2 値になっています。テストのままでも自分では普通に動いてしまうので、配布して初めて壁に気づきます。

テスト中 本番・未確認 本番・確認済み 上限 100 人(テスト登録) 認可が 7 日で失効 未確認アプリの警告 身内でしか使えない 上限 100 人(累計) リセット不可 未確認アプリの警告 配ると枠を食い潰す 上限なし リフレッシュ無期限 警告なし ここがゴール 公開 審査
図1 — 公開ステータスの 3 状態。機微スコープを使う限り、右端に到達しないと一般配布はできない

厄介なのは真ん中の「本番・未確認」で、ここで消費した 100 という枠はプロジェクトの全期間でカウントされ、リセットできません。審査を通す前に配ってしまうと、枠だけ削られます。審査を通せば上限そのものが適用対象外になるので、順番を間違えないことです。

Scope

どのスコープを選ぶかで、手続きの重さが決まる

Google は OAuth スコープを 3 段階に分類していて、この分類が審査の要否を直接決めます。アプリの設計より先に、ここを見て決めるべきでした。

分類手続き
非機微 drive.file 審査不要。ブランド確認のみ
機微 spreadsheets
spreadsheets.readonly
審査あり。数営業日〜10 日程度
制限付き drive / drive.readonly
Gmail 系
審査 + 第三者のセキュリティ監査(CASA)

Google が強く推しているのは drive.file です。これは「アプリが作ったファイル」と「ユーザーが Google Picker で明示的に選んだファイル」だけにアクセスできる、ファイル単位の権限で、非機微なので審査が要りません。

それでも spreadsheets を選んだのは、UX が「スプレッドシートの URL を貼る」だからです。drive.file では、ユーザーが URL で指定した既存ファイルには触れません。Picker を通さないと権限が付かないので、URL 貼り付けという入口そのものが成立しなくなります。

TRADE-OFF

審査で「drive.file で足りるのでは」と指摘される可能性は残ります。正当化の文章を先に用意しておくのが現実的です。ここを押し切れなければ、Picker を実装して非機微スコープに落とすことになります。「審査を通す」と「Picker を作る」のどちらが安いか、という比較で選ぶのが正しい構図でした。

Setup

ブランディングを埋めないと、公開ボタンが押せない

「対象」ページの「アプリを公開」がグレーアウトしているときは、たいていブランディングが未入力です。警告に 「アプリの OAuth 構成が完了していません」 と出ます。実際に入れた値は次のとおりでした。

項目備考
アプリ名MyDictly既定値のままだと事故る(後述)
サポートメール(開発者のアドレス)同意画面に表示される
ロゴ120 × 120 の PNG上げると単体でもブランド確認の対象になる
ホームページhttps://nzw.jp/static/mydictly.html所有権の確認対象になる
プライバシーポリシーhttps://nzw.jp/static/app/mydictly/privacy.htmlホームページと同一ドメインであること
利用規約https://nzw.jp/terms-of-service.html任意だが入れておく
承認済みドメインnzw.jp所有権を確認できるものだけ並べる
デベロッパー連絡先(開発者のアドレス)必須。空だと保存できない

TRAP 1

アプリ名が project-XXXXXXXXXXX のままだった。Firebase 経由で OAuth クライアントを作ると、アプリ名に Google Cloud のプロジェクト番号が入ったままになることがあります。この状態だと、利用者の同意画面に 「project-XXXXXXXXXXX が Google アカウントへのアクセスを求めています」 と表示されます。審査で止まる以前に、まともな利用者なら許可しません。ログインが通っていると気づきにくいので、一度は自分の目で同意画面を見ておくべきでした。

TRAP 2

承認済みドメインに、自分が所有していないドメインが混ざっていた。手元では chromiumapp.org が残っていました。コードから参照が無かったので外しましたが、ここに並んだドメインは所有権の確認を求められうるので、心当たりの無いものは審査前に整理しておくのが安全です。Firebase が自動で足す *.firebaseapp.com は Google 側のドメインなので、そのままで問題ありません。

Trap

本題 — 「ウェブサイトが登録されていません」で止まる

ブランディングを保存して確認に出すと、こう返ってきます。

前回の確認で検出された問題:
・ホームページの URL「https://nzw.jp/static/mydictly.html」の
  ウェブサイトが登録されていません。
  ホームページの所有権を確認します。

これは Google Search Console に、Cloud プロジェクトと同じアカウントでドメインが登録されていないという意味です。HTML 側に何かを書き足す話ではありません(結果的に書き足すことにはなりますが、目的は Search Console の登録です)。

TRAP 3

このダイアログは「前回の確認結果」のキャッシュです。直したつもりで開き直しても、文面は 1 文字も変わりません。「問題は修正した」を選んで再確認をリクエストして初めて評価がやり直されます。ここを知らないと「直したのに変わらない」と延々ループします。

詰まった原因は、レジストラと DNS ホスティングの混同だった

ドメインはお名前.com で取っていたので、当然お名前.com の DNS 設定画面に TXT レコードを追加しました。反映されません。数時間待っても変わりません。

原因はこれでした。

$ whois nzw.jp | grep "Name Server"
[Name Server]  ns-2024.awsdns-61.co.uk
[Name Server]  ns-157.awsdns-19.com
[Name Server]  ns-853.awsdns-42.net
[Name Server]  ns-1059.awsdns-04.org

ネームサーバーが AWS に向いていました。お名前.com は「ドメインを買った場所」であって、実際にレコードを配信しているのは Route 53 です。お名前.com の DNS 設定画面はそのゾーンを参照していないので、いくら書き足しても世界のどこからも見えません。

お名前.com レジストラ ドメインの登録・更新 ネームサーバーの指定 JP レジストリ 委任先の記録 NS: ns-*.awsdns-* =ここが真実 Route 53 DNS ホスティング A / TXT などの実レコード TXT はここに入れる やってしまったこと お名前.com の DNS レコード設定に TXT を追加した → 誰からも参照されない 正しい確認のしかた dig +short TXT nzw.jp \ @ns-157.awsdns-19.com → 空なら未登録。伝播待ちではない
図2 — ドメインを買った場所と、レコードを配信している場所は別物。TXT は右端に入れないと存在しないことになる

ここでの教訓は、切り分けを「待つ」で終わらせないことです。Google のエラーは「DNS の変更が反映されるまでに時間がかかる場合があります」と書いてくるので、つい待ってしまいます。権威サーバーに直接問い合わせれば、伝播待ちなのか未登録なのかは 1 秒で分かります。

# 一般の DNS 経由(キャッシュの影響を受ける)
$ dig +short TXT nzw.jp @8.8.8.8

# 権威サーバーに直接(ここが空なら、そもそも登録されていない)
$ dig +short TXT nzw.jp @ns-157.awsdns-19.com

Solution

決着は「ドメインプロパティを諦める」だった

Search Console のプロパティには 2 種類あります。ドメインプロパティは DNS の確認が必須なので、DNS を触れない・触りたくない状況では選んではいけません。

ドメイン すべてのサブドメイン・http/https を一括 確認方法は DNS のみ DNS を触れないなら選べない URL プレフィックス 入力した URL 配下のみ 確認方法が 4 つある こちらを選んだ 選べる確認方法 HTML ファイル HTML タグ DNS TXT Google Analytics 自動確認された ドメインプロパティは 「全部まとめて確認できる」利点が あるが、今回必要なのは https://nzw.jp/ 配下だけ
図3 — URL プレフィックスなら確認方法が 4 つある。DNS が触れないときの逃げ道になる

そして実際には、ファイルを 1 つも置かずに終わりました。URL プレフィックスで https://nzw.jp/ を登録した瞬間、こう出ます。

所有権を自動確認しました
確認方法: Google Analytics

サイトに gtag.js が入っていて、Search Console と同じ Google アカウントで Analytics を見ていると、それが所有権の証明として使われます。アクセス解析を入れているサイトなら、これが最短経路です。DNS もファイル配置も要りません。

CAUTION

Analytics 方式には「gtag.js を消すと所有権も失効する」という副作用があります。解析タグを外す予定があるなら、Search Console の「設定 → 所有権の確認」から HTML ファイルなどを2 つ目の確認方法として足しておくのが安全です。Google 自身もそう案内してきます。

確認方法触る場所向いている状況
Google Analyticsなし(既存のタグを流用)解析を入れているサイト。最短
HTML ファイルサイトのルートに 1 ファイル静的サイトを自分でデプロイできる
HTML タグトップページの headルートに直接ファイルを置けない構成
DNS TXTゾーンを配信している DNSドメインプロパティが必要なとき

Submit

申請フォームで初めて分かること

スコープの確認申請は「検証センター」から送る。ここまで来て初めて見える制約と要件があり、 知らないと書き直しになる。

正当化文は 1000 文字まで

「スコープの使用方法」の入力欄は 1000 文字が上限。用意していた英文は 1224 文字あって入らず、997 文字まで削ることになった。欄の説明文がそのまま要件なので、 削るときはこの 3 点を残す。

3 番目が最も落ちやすい。Google はいま最小スコープを強く推していて、レビュアーは 「もっと狭いスコープで済むのでは」を第一に疑う。手元では drive.file が「URL で指定した既存ファイルには権限を付けられない」ことを明記した。 これが書かれていないと、それだけで差し戻される。

TRAP 4

「未確認アプリの画面」は動画に映っていなければならない。 申請フォームの注記に 「テストアカウントには未確認アプリの画面が表示されます。これは 想定内の動作であり、動画に映っている必要があります」 とある。 警告画面は「見せたくないもの」に見えるので飛ばして撮りたくなるが、逆で、 飛ばすと要件を満たさない

TRAP 5

デモ動画を Shorts にしない。Shorts は縦向き(9:16)なので、 デスクトップのブラウザを撮った横長の映像を上げると上下に余白が入り、 アドレスバーの client_id が読める大きさで映らない。 動画の中心要件が潰れる。横向きの通常動画として上げ、リンクも watch?v= 形式にする。

録画は本番トラフィックでやらない

フォームにこう書かれている。「アプリがすでに公開されている場合は、未確認のスコープを 本番環境のトラフィックにデプロイしないでください。未確認のユーザー割り当てが消費されます」。 収録に使うアカウントは、あの 100 人枠を 1 消費する。同じアカウントで撮り直す分には 増えないが、テスターを集めて撮るようなことはしないほうがよい。

「詳細」欄はレビュアーの疑問を潰す場所

最後に自由記述の「詳細」欄がある。空でも送信できるが、 先回りして疑問を潰しておく欄だと考えるとよい。手元では次を書いた。

YouTube チャンネルが要る

動画は限定公開の YouTube 動画でなければならない。Drive の共有リンクや 自前サーバーでは受け付けない。チャンネルを持っていないと、ここで初めてチャンネル作成に回される。

チャンネル名は何度も弾かれることがある。ここで注意したいのは、 「使用できない名前の入力回数が上限を超えました」は回数制限であって、 いま入力している名前への判定ではないこと。上限に達したあとは有効な名前でも同じ エラーが出るので、名前を変え続けても意味がない。24 時間待つか、 既にチャンネルを持つ別の Google アカウントから上げる。 動画の所有アカウントは Cloud プロジェクトと別で構わない。

Checklist

同じところで詰まらないために

  1. アプリ名を確認する。project-XXXXXXXX のままなら、同意画面にその文字列が出る。
  2. ホームページとプライバシーポリシーを同一ドメインに置く。別ドメインだと審査で止まる。
  3. Search Console のプロパティは、Cloud プロジェクトと同じアカウントで作る。他人のアカウントで確認済みでも意味がない。既存の所有者がいるなら、その人に自分を所有者として追加してもらうのが最短。
  4. URL プレフィックスは表記が完全一致でないと効かない。http://https://www の有無は別プロパティ扱い。
  5. DNS を触る前に whois でネームサーバーを見る。ドメインを買った場所と、レコードを配信している場所は別物。
  6. 「反映待ち」と言われても待たない。権威サーバーに dig で直接聞けば、未登録かどうかは即分かる。
  7. 直したら「問題は修正した」を押す。ダイアログは前回の結果を表示しているだけで、勝手には更新されない。
  8. プライバシーポリシーに Limited Use の一文を入れる。Google API から取得した情報の扱いがポリシーに準拠する旨の明記を求められる。
  9. 正当化文は 1000 文字に収める。書いてから数えるのではなく、削る前提で組む。
  10. 動画は横向き。未確認アプリの警告画面を飛ばさない。Shorts にしない。
  11. 承認済みドメインから、所有していないドメインを外しておく。

Next

ブランド確認は通過点でしかない

所有権が確認されると、ブランディングのページに 「ブランディングは検証済みで、ユーザーに表示されています」 と出ます。ここで終わりではありません。これはアプリ名・ロゴ・URL が本物だと認められただけで、機微スコープを使う権利はまだ得ていないからです。

残っているのは次の 3 つでした。

ブランド確認と機微スコープ審査は別々のプロセスで、前者が通っても後者は自動では始まりません。ここを取り違えると「確認済みと出ているのに、いつまでも警告画面が消えない」ことになります。