最初に守ること:認証より認可
APIセキュリティでは、ログイン済みかだけでなく、その利用者が、そのデータと操作を実行してよいかをサーバー側で毎回確認します。 OWASP API Security Top 10でも、オブジェクト単位の認可不備(BOLA)は重要なリスクです。

悪い例: /api/orders/123 の 123 を受け取り、その注文を返す
必要な確認: 注文123の所有者または許可された役割が、現在の利用者か確認してから返す
画面でボタンを隠すだけでは認可になりません。URL、ID、役割、公開してよい項目をAPI側で検証します。
認証トークンを安全に扱う
トークンを受け入れる時は、署名、発行者、対象者、期限、用途を確認します。JWTのペイロードを秘密情報として扱わず、ログにもトークン全体を残しません。パスワード再設定やログイン試行は、通常のAPI以上にブルートフォース対策と監視が必要です。
入力と出力を別々に検証する
- 入力は型、長さ、形式、許可値をサーバーで検証する
- 更新できる項目を明示し、受け取ったJSONをそのまま保存しない
- 出力は利用者の権限ごとに必要な項目だけ返す
- URLを取得する機能は、内部ネットワークへのアクセス(SSRF)を防ぐ設計にする
SQLは文字列結合ではなく、使用するDBドライバやORMのパラメータ化されたクエリを使います。
レート制限は保護策の一つ
レート制限は、ログイン、パスワード再設定、注文、投稿など、濫用されると損害が大きい操作に適用します。利用者ID、APIキー、または信頼できるプロキシから渡されたIPを識別子にし、拒否時は429 Too Many Requestsを返します。
実装は利用するプラットフォームで異なります。次は特定SDKに依存しない疑似コードです。
key = authenticatedUserId ?? trustedClientIp(request)
result = rateLimiter.check("password-reset:" + key)
if result.allowed is false:
return 429 with Retry-After when result.resetTime is known
continue the request
プロキシ構成を確認せずにX-Forwarded-Forを信頼すると、利用者が値を偽装できることがあります。分散型の制限では、障害時に拒否するか通すかも決めます。Upstashを使う場合は、現在のSDKでratelimit.limit(identifier)が返すsuccess、remaining、resetを扱います。
ログと監査
監査には、誰がいつどの操作をしたか、結果、対象の識別子を残します。一方で、パスワード、認証ヘッダー、アクセストークン、個人情報をログに含めません。異常な失敗率や認可失敗を観測できるようにします。
リリース前の確認
- 他人のIDへ差し替えても、データを読んだり更新したりできないか
- 権限のない項目を入力・出力できないか
- 期限切れ、別発行者、別用途のトークンを拒否するか
- 敏感な操作にレート制限、監視、復旧手順があるか
- エラーやログから秘密情報を取得できないか
まとめ
APIを安全にする中心は、サーバー側の認可です。認証、入力検証、出力の絞り込み、レート制限、監査を重ね、利用者が送る値や画面の表示だけを信頼しない設計にします。