FastAPIのセキュリティは、一つの機能を追加すれば完成するものではありません。
利用者の本人確認、操作権限、ブラウザからの接続元、リクエスト量、実装上の欠陥は、それぞれ別の仕組みで管理します。
この記事では、認証と認可、JWT、CORS、APIキー、レート制限、脆弱性診断の役割を分け、FastAPIで設計するときの判断順を整理します。
掲載するコードは構造を説明するための最小例です。データベース、秘密情報の保管、鍵の更新、監査ログ、障害時の処理まで含む完成品ではありません。
最初に分けたい六つの対策
似た用語を同じ対策として扱うと、設定を追加しても守れない経路が残ります。
| 対策 | 確認すること | 単独では防げないこと |
|---|---|---|
| 認証 | 誰がリクエストしたか | その利用者が何を操作できるか |
| 認可 | その操作を許可してよいか | 利用者本人の確認 |
| CORS | どのオリジンのブラウザ画面に応答を読ませるか | ブラウザ以外からのAPI呼び出し |
| APIキー | どのクライアントが呼び出したか | キーを使う個人の本人確認 |
| レート制限 | 一定時間に受け付ける量 | 許可された回数内の不正操作 |
| 脆弱性診断 | コードや稼働中APIに既知の問題がないか | 要件や権限設計そのものの妥当性 |
この区別を設計書とテスト項目にも反映すると、対策の目的と担当箇所を追いやすくなります。
OAuth2とJWTによる認証
認証は、リクエストを送った主体を確認する処理です。
FastAPIでは、OAuth2のBearerトークンを依存関数で受け取り、署名や有効期限を検証して利用者を特定する構成を作れます。
JWT(JSON Web Token)は、JSON形式の情報に署名を付けて受け渡すための形式です。署名によって改変を検出できますが、内容を暗号化する仕組みではありません。
JWTの構造、保存場所、失効管理は、JWTの仕組みと安全に使うための注意点でも整理しています。
トークン発行と検証の最小構成
次の例は、秘密鍵をソースコードに固定せず、環境変数から読む構成です。
import os
from datetime import datetime, timedelta, timezone
import jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jwt.exceptions import InvalidTokenError
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
SECRET_KEY = os.environ["JWT_SECRET_KEY"]
ALGORITHM = "HS256"
def create_access_token(subject: str, expires_minutes: int = 30) -> str:
expires_at = datetime.now(timezone.utc) + timedelta(minutes=expires_minutes)
payload = {"sub": subject, "exp": expires_at}
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
def get_current_subject(token: str = Depends(oauth2_scheme)) -> str:
unauthorized = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="認証情報を確認できません",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
subject = payload.get("sub")
if not subject:
raise unauthorized
return subject
except InvalidTokenError:
raise unauthorized
subには利用者を一意に識別できる値を入れ、expには有効期限を入れます。
一方、ログイン処理では保存済みのパスワードハッシュを検証します。平文パスワードをコードやデータベースに保存する構成は避け、利用するJWTライブラリとハッシュライブラリは導入時のFastAPI公式資料に合わせて選びます。
本番実装でコード例に足すもの
- 認証失敗時に、利用者の存在や失敗理由を必要以上に明かさないエラー応答
- 秘密鍵をリポジトリへ置かない保管方法と更新手順
- トークンの有効期限、失効、再発行に関する運用ルール
- 認証の成功と失敗を追跡でき、トークン本体を残さない監査ログ
認可は認証の後で判定する
認可は、認証済みの主体に特定の操作を許すかを決める処理です。
ログインできたことと、管理者向けのデータを読めることは別の条件です。
ロールベース認可では、管理者、編集者、閲覧者などの役割に許可を割り当て、エンドポイントごとに必要な役割を依存関数で確認します。
- トークンを検証して主体を特定する
- 信頼できるデータから現在のロールや権限を取得する
- 対象エンドポイントに必要な権限と照合する
- 認証できない場合は401、権限が足りない場合は403として扱う
権限をトークンに含める場合も、権限変更がいつ反映されるかを決める必要があります。短い有効期限、失効の仕組み、サーバー側での再確認のどれを使うかは、要求される即時性に合わせます。
役割だけでは表現しにくい権限には、OAuth2スコープのような細かな許可単位を検討できます。ただし、権限の種類が少ないAPIへ複雑な仕組みを持ち込むと、設定と確認の負担も増えます。
CORSが制御する範囲
CORS(Cross-Origin Resource Sharing)は、別のオリジンで動くブラウザ上のJavaScriptに、APIの応答を読ませるかを制御する仕組みです。
オリジンは、通信方式、ドメイン、ポートの組み合わせです。ドメインが同じでも、HTTPとHTTPS、またはポートが違えば別のオリジンとして扱われます。
CORSは認証や認可の代わりにはなりません。ブラウザ以外のクライアントはCORSによる制御の対象ではないため、API自体には認証と認可が必要です。
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://your-frontend.example"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Authorization", "Content-Type"],
)
本番環境では、実際に必要なオリジン、メソッド、ヘッダーを列挙します。認証情報を伴う通信では、許可元をワイルドカードにせず明示します。
フロントエンドとのAPI契約や配信方法も含めて設計する場合は、FastAPIとフロントエンド連携の設計ポイントも参照してください。
APIキーとレート制限の役割
APIキーは、連携先のシステムや契約単位など、APIを利用するクライアントを識別するために使います。
利用者個人の本人確認が必要なAPIでは、APIキーだけで済ませず、利用者向けの認証と組み合わせます。
- 推測されにくいキーを発行し、所有者と許可範囲を管理する
- キーをソースコード、URL、通常のアクセスログへ残さない
- 失効と再発行の手順を用意する
- 漏えい時に影響範囲を絞れる単位でキーを分ける
レート制限は、一定時間に受け付けるリクエスト量を制御する仕組みです。
元記事で例示していたslowapiのようなライブラリを使う場合も、IPアドレス、APIキー、利用者のどれを基準に数えるかを先に決めます。
共有回線やプロキシの背後では複数の利用者が同じ送信元に見えることがあるため、IPアドレスだけを基準にすると正当な利用まで制限する可能性があります。
静的解析と動的診断を使い分ける
静的解析はソースコードを調べ、危険な書き方や設定の候補を探します。元記事で挙げたBanditはPythonコードを対象にできます。
動的診断は稼働中のAPIへリクエストを送り、応答や振る舞いを確認します。OWASP ZAPはこの用途で使われます。
両方をCI/CDへ組み込むと変更のたびに確認できますが、検査を通過しても権限設計が正しいとは限りません。
診断結果は、再現条件、影響する機能、修正後の再試験まで記録し、誤検知と未対応を区別します。
本番公開前の確認項目
- 認証と認可を別々のテスト項目にしている
- パスワードを安全な方法でハッシュ化し、平文を保存していない
- JWTの署名、有効期限、主体を検証している
- 秘密鍵とAPIキーをコードやログへ残していない
- CORSで許可するオリジン、メソッド、ヘッダーを限定している
- 権限変更、キー漏えい、トークン失効時の手順がある
- レート制限の単位と、制限時の応答を決めている
- 静的解析と動的診断の結果を確認し、修正後に再試験している
アプリケーション全体のテスト、監視、運用まで確認するには、FastAPIを本番運用へ進める実務チェックリストも役立ちます。
安全なAPIへつなげる設計順序
FastAPIのAPIを守るには、認証、認可、CORS、APIキー、レート制限、脆弱性診断を目的別に組み合わせます。
まず主体と権限を分け、次にブラウザの接続元と利用量を制御し、最後に静的解析と動的診断で実装を点検します。
サンプルコードをそのまま本番へ移すのではなく、秘密情報の保管、失効、監査、障害時の手順まで設計してから公開してください。
この記事に関連する株式会社greedenの取り組み
認証や権限、CORSを個別に足すだけでは、運用時の抜けを防げません。株式会社greedenは、要件定義からAPI設計、実装、テスト、保守まで一気通貫で支援し、安全性を含むWebシステム開発に伴走します。

