Expo APIキーの秘密管理:アプリに入れてよいキーは?
著者:Mehdi Azizi
更新・7 分
秘密のAPIキーはExpoアプリに入れず、サーバーに置きます。Supabaseの公開キーとシークレットキーを区別し、2つのテストアカウントでアクセス制御を確認しましょう。
環境変数だからといって秘密とは限らない
Expoアプリでは、EXPO_PUBLIC_ で始まる変数はアプリのコードで使うためのものです。サーバー用の秘密の値を入れてはいけません。Expoの説明によると、これらの値はコンパイル後のJavaScriptに埋め込まれ、アプリのユーザーが読み取れます。つまり、キーを .env ファイルに移すだけでは保護になりません。出典:Expoの環境変数
AIに「APIをつないで」と頼む前に、渡すものを分類してください。サービスのアドレスなのか、公開される前提のキーなのか、それとも特権的な操作を許可するキーなのか。この分類で、コードをどこで実行すべきかが決まります。
次の表は設計のための目安で、あなたのアプリの監査ではありません。
| 要素 | 置き場所 | 確認すべきこと |
|---|---|---|
| バックエンドの公開アドレス | アプリの設定 | 正しい環境を指しているか。 |
| Supabaseのpublishableキー、または旧anonキー | 権限が正しく設定されていればアプリ | データのルールが、他のユーザーのアカウントへのアクセスを実際にブロックしているか。 |
| Supabaseのsecretキーまたはservice_roleキー | サーバーのみ | モバイルのバンドルにも、クライアントから見えるログにも出てこないか。 |
| AIプロバイダーのシークレットキー | サーバーのみ | アプリは自分のサーバーを呼び出し、サーバーがユーザーと利用制限を確認してからプロバイダーを呼んでいるか。 |
Supabaseは、クライアント向けのキーと、信頼できる環境向けのシークレットキーを区別しています。公開キーはプロジェクトを識別するものであり、データに対する権限の代わりにはなりません。出典:Supabase APIキー
例:架空の読書記録アプリ
レアとサミが本と個人的なメモを記録するアプリを考えてみます。この例はテストの準備用で、Devoriaのアプリで得た結果を示すものではありません。
通常の流れは問題なさそうに見えます。レアがログインすると自分のメモが見えます。でも、これではまだ大事な問いに答えていません。レアがサミのメモを狙ったリクエストを送ったとき、サーバーはそれを拒否するでしょうか?
「ログイン中のユーザーのメモを表示する」といったUI上のフィルターは、表示を整えるだけです。権限チェックはデータ側でも適用する必要があります。SupabaseではRow Level Securityのルールで、セッションに応じてアクセスできる行を制限できます。SupabaseはAPIで公開されるテーブルでの有効化を推奨しており、読み取りと書き込みのポリシーについて説明しています。出典:Row Level Security
自分のテスト用プロジェクトでは、各メモを所有者に紐づけ、誰が読めるか、作成できるか、編集できるか、削除できるかをそれぞれ定義してください。ファイルも確認しましょう。データベースの行を保護しても、画像が非公開になっている証明にはなりません。
2つのテストアカウントで行う確認手順
自分で管理できるアカウントを2つ用意し、それぞれに別の本と、見分けやすい短いメモを入れておきます。許可されたテスト環境で、架空のデータを使ってください。
- 自分のメモを読む。 アカウントAでメモAが見つかる。
- AからBのメモを読む。 リクエストで非公開の内容が漏れない。
- AからBのメモを編集する。 サーバーが拒否し、メモBは変わらない。
- AからBの名義で作成する。 サーバーがその名義付けを拒否する。
- セッションなしで読む。 非公開の内容が何も返らない。
- AからBの非公開ファイルを開く。 ファイルにアクセスできない。
実際の結果、テストしたバージョン、エラーがあればその内容を記録してください。「ルールは有効になっている」はテスト結果ではありません。リソースにある確認シートを、こうした証拠を残すたたき台に使えます。
有料の呼び出しは自分のサーバーを経由させる
AIのAPIで本を要約する機能なら、流れは「アプリ → 自分のサーバー → プロバイダー → 自分のサーバー → アプリ」になります。シークレットキーはサーバーに残ります。ただし、この構成だけでは不十分です。サーバーへのアクセスも制御する必要があります。
架空の例では、サーバーは特に、セッションの確認、その本が本人のものかの確認、繰り返しのリクエストの制限、プロバイダーが応答しないときのわかりやすいエラーの返却を行う必要があります。ユーザーが有料アクセスを持つかどうかを、クライアント自身が決めてはいけません。
4つのテストを用意しましょう。未ログインのユーザー、別アカウントの本、上限到達、プロバイダー停止です。最後のテストでは、アプリが入力内容を失わずにローディング状態から抜けられるかを確認します。
コーディングアシスタントに頼めること
自分のリポジトリに合わせて使えるレビュー用の指示です。秘密の値は貼り付けないでください。
モバイルのコードとサーバーで使われている変数を、名前だけを表示して一覧にしてください。クライアント側にある特権的な呼び出しを特定してください。非公開データについて、読み取りと書き込みのチェックを説明し、2つのテストアカウントを使った確認手順を提案してください。承認なしにキーのローテーションや本番環境の変更は一切行わないでください。
返答は該当するコードと照らし合わせて読んでください。アシスタントは不整合を見つけられますが、その返答はテストの実行の代わりにはなりません。Claude Codeでアプリを作るのガイドで、この作業の分け方を説明しています。
アプリ開発を続ける前に
次の3つをシンプルに説明できるようにしておきましょう。どの値が公開されるのか、どの処理がサーバーを通るのか、あるアカウントが他のアカウントのデータを見られないことをどのテストが示すのか。どれか1つでも曖昧なら、機能を追加する前にはっきりさせてください。
iPhoneアプリを作るのページでは、このステップをプロジェクト全体の中に位置づけています。順番に進めたいなら、iOS Kitに4ステップの道筋と、アカウントとAIがすでに組み込まれたスターターコードがあります。どのステップから再開すればいいかわからなくなったら、無料の診断でプロジェクトの順序を整理し、僕のApple審査リジェクト対策チェックリストをお送りします。
よくある質問
Expoアプリで秘密のAPIキーはどこに置けばいいですか?
自分のサーバーです。アプリには絶対に入れません。Supabaseのsecretキーやservice_roleキーも、AIプロバイダーのシークレットキーも、サーバー側だけに置きます。アプリは自分のサーバーを呼び出し、サーバーがユーザーと利用制限を確認してからプロバイダーを呼びます。これらのキーがモバイルのバンドルにも、クライアントから見えるログにも出てこないことを確認してください。
Expoでは.envファイルでAPIキーを守れますか?
それだけでは守れません。EXPO_PUBLIC_ で始まる変数はアプリのコード用で、サーバー用の秘密を入れてはいけません。Expoの説明では、これらの値はコンパイル後のJavaScriptに埋め込まれ、アプリのユーザーが読み取れます。キーを .env ファイルに移すだけでは保護になりません。
公開APIキーとシークレットキーの違いは何ですか?
公開キーはアプリに含めて配布する前提のキーです。プロジェクトを識別しますが、データに対する権限の代わりにはなりません。シークレットキーは特権的な操作を許可するもので、信頼できる環境だけで使います。Supabaseでは、publishableキー(または旧anonキー)は権限が正しく設定されていればアプリに置けます。secretキーとservice_roleキーはサーバーに置きます。
キーを漏らさずにExpoアプリからAIのAPIを呼ぶには?
自分のサーバーを経由させます。アプリがサーバーを呼び、サーバーがプロバイダーを呼んで、その返答をアプリに返します。シークレットキーはサーバーに残ります。サーバーはさらに、セッションを確認し、繰り返しのリクエストを制限し、プロバイダーが応答しないときはわかりやすいエラーを返す必要があります。ユーザーが有料アクセスを持つかどうかを、クライアント自身が決めてはいけません。
各ユーザーが自分のデータしか見られないことはどう確認しますか?
自分で管理できるテストアカウントを2つ用意し、それぞれに見分けやすいメモを入れます。アカウントAから、Bのメモを読む、編集する、Bの名義で作成する、Bの非公開ファイルを開く、を試します。セッションなしのテストも行いましょう。どのリクエストも拒否されるか、何も漏らさないことが条件です。実際の結果を記録してください。「ルールは有効になっている」はテスト結果ではありません。
アプリのキーをAIにチェックしてもらうにはどう頼めばいいですか?
モバイルのコードとサーバーの変数を、名前だけを表示して一覧にするよう頼みます。秘密の値は貼り付けないでください。クライアント側にある特権的な呼び出しの特定と、2つのテストアカウントを使った確認手順の提案も頼みましょう。承認なしのキーのローテーションや本番環境の変更は禁止してください。AIの返答はテストの実行の代わりにはなりません。