Q1リクエストに API キーを添えて送ると、外部サービスは何を決められますか。
API キーと外部サービス連携 — キーが守るもの・ Webhook
この記事は、プログラミングやバイブコーディングをする上で最低限身につけたほうがよい IT の実践的な知識を 1 から身につける「IT 基礎知識講座の一部」です。
API キーは、その呼び出しが誰のものかを示す文字列です。置いてよい場所と、外部サービスの側から呼ばれる Webhook の向きを図解で確かめます。
この記事は、外部サービスを呼び出すときに使う API キー と、外部サービスの側から呼ばれる Webhook の 2 つを扱います。
キーをどこで発行するのか、何を示す文字列なのか、どこに置けば読める人が増えないのかまで確かめます。
- API キーをどこで発行し、呼び出しのどこに添えるか
- キーが呼び出しの持ち主を示す文字列であることと、従量課金との関係
- キーを置いてよい場所と、ブラウザに届く場所に書くと何が起きるか
- 外部サービスの側から呼ばれるWebhookと、署名の照合
API キーは、使う外部サービスの管理画面で発行する
外部サービスを呼ぶには、まずその提供側からAPI キー(API key。呼び出しがどの利用者のものかを提供側に示す文字列)を受け取ります。
自分で決める値ではなく、使うサービスの側が発行して渡す値です。
決済でも地図でも文章の生成でも、登録する・発行する・自分のサーバーに置くという並びは変わりません。
発行された文字列は、その場でコピーして自分のサーバーの .env に置きます。
外部サービスの多くは従量課金(使った分だけ料金がかかる形)で、呼び出した回数や送受信した量に応じて請求されます。
キーが外に出れば、他人が呼び出した分も持ち主の請求に入ります。
API キーは、その呼び出しがどの利用者のものかを示す文字列
決済サービスの API は公開された URL なので、届いた呼び出しが誰のものかを知る手段が要ります。
添える場所は URL ではなく、リクエストヘッダー(request header。本体とは別に、送り主や形式などを名前と値の組で並べる部分)です。
- POST https://api.pay.example.com/v1/charges
- どこへ何をしに行くかだけを書く
- API キーを書くのはここ
- Authorization: Bearer sk_live_a1b2
- 名前と値の組を 1 行に 1 つ並べる
- 送るデータを JSON で入れる
- 取得だけの呼び出しでは空のことが多い
真ん中の枠の 2 行目が、キーを書く 1 行です。
Authorization がヘッダーの名前、Bearer が渡し方を表す語、その後ろがキーの値です。
この名前も書き方も、決めているのは提供側です。
届いたキーで決済サービスが決めるのは、持ち主・許した操作・回数の 3 つです。
| my-app がしたこと | Authorization ヘッダー | 決済サービスがすること | 返るもの |
|---|---|---|---|
| 支払いの一覧を取得 | Bearer sk_live_a1b2 | 持ち主を決めて範囲を確かめる | 200 と JSON |
| 支払いの一覧を取得 | 付け忘れた | 持ち主を決められない | 401 が返る |
| 支払いを 1 件作る | Bearer sk_read_9f3c | 読み取りしか許していない | 403 が返る |
| 短い間に何度も呼ぶ | Bearer sk_live_a1b2 | 持ち主ごとに回数を数える | 429 が返る |
401 ならキーの値とヘッダーの名前を、403 なら許されている操作を確かめます。
4 行目の上限がレート制限(rate limit。一定の時間に受け付ける呼び出しの回数の上限)で、超えると 429 が返ります。
キーは呼び出しの持ち主を示す文字列
API キーは、この呼び出しは誰のものかを伝えるためだけの文字列です。
決済サービスはキーを見て持ち主と許した操作を確かめ、その人の回数を数えるので、キーが無ければ 401、許していない操作なら 403、回数が多すぎれば 429 が返ります。
キーはブラウザに届くコードに置かず、自分のサーバーの中だけに置く
キーを持っている人は誰でも、その持ち主として呼び出せます。
本人かどうかを画面で確かめる仕組みはありません。
- PAY_API_KEY=sk_live_a1b2
- コードとは別のファイルに置く
- .env から読んだキーを呼び出しに添える
- ファイルそのものは端末に送らない
- index.html と script.js
- 決済サービスを直接呼ばず、自分のサーバーに頼む
- ブラウザから使う前提で発行されたキーだけを置く
同じキーでも、書いた場所によって読める人が変わります。
| キーを書いた場所 | 端末に届くか | 読める人 | 起きること |
|---|---|---|---|
| .env(サーバーの中) | 届かない | サーバーを触れる人だけ | 契約どおりに使える |
| script.js | 届く | 画面を開いた人全員 | 他人が本人として呼べる |
| 公開した server.js | 届かないが公開される | コードを見た人全員 | Git の履歴から消せない |
読める人が増える行ほど、他人が本人として呼び出せる状態に近づきます。
3 行目はブラウザには届きませんが、一度 Git に記録すると、あとで消しても変更履歴からは読めます。
手順の「.env に入れてください」は、1 行目の置き方にするための指示です。
外に出てしまったキーにできることは 2 つで、効き目は同じではありません。
読み取られた値は有効なままで、Git の変更履歴にも残ります。
右が失効(revoke。発行済みのキーを提供側で使えない状態にすること)です。
キーは端末に届かない場所だけに置く
キーは、それを持っている人なら誰でも本人として使えます。
だから利用者の端末に届くファイルにも公開するコードにも書かず、うっかり外に出したときは、書いた文字を消すのではなく失効させて新しいキーを発行し直します。
Webhook は、外部サービスの側から自分のサーバーが呼ばれる仕組み
支払いの完了や返金は、いつ起きるか呼ぶ側には分からない出来事です。
繰り返し尋ねると無駄な呼び出しが増え、気づくのも遅れます。
Webhook(webhook。決められた出来事が起きたときに、外部サービスの側から登録済みの URL へリクエストが送られる仕組み)は、この向きを逆にします。
3 行目の Webhook だけが、決済サービスから my-app へ送る向きです。
用意するのは、通知を受け取る URL を 1 つ登録しておくことだけです。
支払いが完了したとき、領収書ができたとき、返金されたときに、それぞれ別の通知が届きます。
どの出来事の通知かは、リクエストの本体に書かれています。
矢印 1 は自分から呼ぶ向き、矢印 2 は外部サービスから呼ばれる向きです。
キーが渡るのは決済サービスだけで、利用者の端末には届きません。
Webhook は向きが逆の呼び出し
Webhook は、決済サービスの側から my-app が呼ばれる呼び出しです。
いつ起きるか分からない出来事を起きた時点で知らせてもらうためのもので、用意するのは通知を受け取る URL を 1 つ作って登録しておくことだけです。
通知を受け取る URL は誰でも呼べるので、署名を照合してから処理する
通知を受け取る URL は公開されているので、決済サービス以外の誰かも同じ URL に送れます。
これを防ぐのが署名(signature。送り主と受け取る側だけが知っている文字列から計算した値を添え、受け取る側が同じ計算で照合する仕組み)です。
- POST https://my-app.example.com/webhooks/payment
- 自分で用意して登録した URL
- 署名が入るのはここ
- 同じ通知を見分ける ID もここに入ることが多い
- どの出来事かが JSON で書かれている
- 支払いの ID や状態もここに入る
中身を読む前に、ヘッダーの署名を照合します。
成功を返さなかったときに、送る側が同じ通知をもう一度送ることが再送(retry)です。
通知ごとの ID を記録し、処理済みは読み飛ばします。
照合に使う文字列も API キーと同じくコードに書かず、付け方は API ドキュメントで確かめます。
手順書の「署名を検証してください」は、この照合のことです。
読む前に照合し、2 回目に備える
通知を受け取る URL は公開されているので、届いただけでは送り主が分かりません。
本体を読む前に署名を照合し、合っていたら記録を更新して成功のステータスコードを返し、処理した通知の ID を覚えておいて 2 回目は読み飛ばします。
理解度チェック
まずは1問ずつ答えてみましょう。
Q2API キーをブラウザに届くコードに書くと、何が問題ですか。
Q3Webhook で届いた通知を受け取ったとき、中身を読む前に行うことはどれですか。