2025.3.16
クライアントサイドでAPIキーどうすればいいんだ問題【ChatGPT会話備忘録】
ChatGPTに教えてもらったことを備忘録としてまとめる。合っているかは保証しません。
今回はクライアントサイドでのAPIキーについて。
1. クライアントにAPIキーを持たせるのは基本NG
ReactとかNext.jsとか、ブラウザで動くアプリでは、アプリのコードはユーザーに丸見え。
Webpackでバンドルしようが、Viteで爆速ビルドしようが、結局はJavaScriptとして配られる。
当然、APIキーが埋め込まれていれば、DevToolsでちょっと見ればバレる。
難読化しても無意味。誰でも取得できる=誰でも使えてしまう。
いったん漏れれば、APIの不正利用 → サービス側の課金爆発 or 停止、みたいな最悪パターンも普通にある。
2. 環境変数に入れても隠せるわけじゃない
Next.jsならNEXT_PUBLIC_
付きの環境変数があるけど、これはビルド時にJSに埋め込まれるだけ。
.env
に書いてると「サーバーサイドだけで使われる」感が出るけど、NEXT_PUBLIC_API_KEY
なんて書いたら、最終的にmain.js
のどっかにベタっと載ってる。
つまり、「環境変数=安全」ではないということ。
クライアントに渡した時点でアウト。
3. 認証と認可で守るべき
APIキーはあくまで**「アクセスの目印」**であって、セキュリティ機構ではない。
言ってしまえば「合言葉」。それだけで門番を突破できるのは雑すぎる。
理想的なのは:
- ユーザーごとにログイン(=認証)
- 権限ごとにアクセス制御(=認可)
- トークン(JWTやOAuthなど)を使ってアクセス権を管理
たとえば、SPAならログインしてIDトークン取得→それをAuthorizationヘッダに付けてAPIアクセス、という流れが定番。
APIキーはログインなしで誰でも使えるので、「公開されてないけど実質オープンAPI」状態になりがち。
4. 認証なしでも使いたいAPIの場合
中には「認証が不要な軽いAPI」もある。
たとえば天気APIや地図APIみたいな、ユーザーの操作によって叩くタイプのもの。
ただし、認証しない=守らなくていいではない。
最低限でも以下の対策は考えるべき:
- サーバーサイドで一時トークンを発行してJSに埋め込む
- リファラーチェックで許可されたドメインだけ許可
- IP制限(Bot除け)
- CAPTCHAやレートリミットで大量リクエストを防ぐ
正直、ここまでやるくらいならサーバー経由のプロキシを挟んだ方が安全で制御しやすい。
5. APIキーを扱うときの最低ライン
シーン | 方法 |
---|---|
サーバーからのアクセス | サーバーの環境変数にAPIキーを置く。サーバーから直接叩く |
クライアントから直接叩きたい時 | 基本NG。どうしても必要ならCloud Functions等で中継する |
Firebase, Stripeなどのケース | 公開キーと秘密キーを分けて設計。クライアント側は公開キーだけ |
特にFirebaseやStripeみたいなサービスは「クライアントから叩いてもOKな設計」がされてる。
とはいえ、その前提をよく確認せずにAPIキーを埋め込むのは危険。
6. トークンベース認証への移行
APIキーよりも現代的な選択肢は「アクセストークン(JWTなど)」。
AWSなら:
- Cognitoで認証
- API Gateway+IAMでトークン制御
Firebaseなら:
firebase.auth()
でログインgetIdToken()
でIDトークンを取得- それをAPIのAuthorizationヘッダに付ける
こうすれば、ユーザーごとのアクセス制御やロール管理もできる。
しかもAPIキーより安全。
まとめ
クライアント側にAPIキーを持たせるのは原則NG。
APIを守るなら:
- トークンベースの認証(JWT、OAuthなど)
- サーバー経由でプロキシする構成
- CORS、レート制限、IP制御などの併用
これが基本。