Open1
【認証・許可系/Auth系】API認証の設計/実装について📝
【認証・許可系/Auth系】API認証の設計/実装について📝
「API 認証をどう設計・実装するか」 を目的別に整理し、FastAPI や Node(Hono/Express)での実装例、そして OWASP 最新ガイドラインに基づくベストプラクティスまでまとめます。
1. まず整理すべき4つの観点
| 観点 | 具体的に決めること |
|---|---|
| 主体 (Who) | 第三者アプリ?自社 SPA?サーバ間バッチ? |
| 方式 (How) | API キー / Basic / Bearer(JWT) / OAuth2 / mTLS など |
| 有効期間 (When) | 使い捨ての短命トークンか、長期 API キーか |
| 権限範囲 (What) | スコープ / RBAC / ABAC / テナント分離方法 |
2. 代表的な認証方式比較
| 方式 | 主なユースケース | ステートレス | トークン失効の難しさ | 実装ライブラリ例 |
|---|---|---|---|---|
| API キー (HMAC でも可) | 内部連携・Webhook 検証 | ◯ | 中 | FastAPI: Header() / Node: Hono c.req.header()
|
| HTTP Basic | 単純な PoC、VPN 内限定 | ◯ | 低 | Same as above |
| Bearer (JWT) | SPA ↔ API、モバイルアプリ | ◯ | 高 (要ブラックリスト or 短寿命) | FastAPI OAuth2PasswordBearer, PyJWT / Node jsonwebtoken
|
| OAuth2 Client Credentials | サーバ間 (Machine-to-Machine) | ◯ | 中 | FastAPI Authlib / Node simple-oauth2
|
| OAuth2 Authorization Code + PKCE | 外部サードパーティ連携 | ◯ | 中 | Same as above |
| OpenID Connect | 「ログインして誰かを識別」 | ◯ | 中 | Same as above |
| Mutual TLS | 金融・社内ゼロトラスト | ◯ | 低 | Web サーバ設定+CA 運用 |
3. Bearer(JWT)トークン実装ステップ(FastAPI 例)
from datetime import timedelta, datetime
from jose import jwt, JWTError
from passlib.context import CryptContext
from fastapi import Depends, Header, HTTPException, status
SECRET_KEY = "<<<強力なランダム文字列>>>"
ALGORITHM = "HS256"
ACCESS_LIFETIME = timedelta(minutes=30)
pwd_ctx = CryptContext(schemes=["bcrypt"], deprecated="auto")
def create_access_token(sub: str) -> str:
exp = datetime.utcnow() + ACCESS_LIFETIME
to_encode = {"sub": sub, "exp": exp}
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/token")
async def get_current_user(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload["sub"]
except JWTError:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
-
/auth/tokenでパスワードを受け取り、create_access_token()を返す - 守りたいエンドポイントで
Depends(get_current_user)を挟むだけで認証完了
FastAPI デフォルトのドキュメント UI でも「Authorize」ボタンが自動表示されます (FastAPI, FastAPI)
4. API キーを 1 つのエンドポイントだけに付ける(Node / Hono 例)
import { Hono } from 'hono';
const API_KEY = process.env.FASTAPI_MCP_API_KEY ?? 'secret-fast-api-mcp-token';
const app = new Hono();
// 認証付き
app.get('/protected', (c) => {
const key = c.req.header('x-api-key');
if (key !== API_KEY) return c.json({ error: 'Unauthorized' }, 401);
return c.text('OK!');
});
// 認証不要
app.get('/public', (c) => c.text('Hello, World!'));
export default app;
- 環境変数にキーを置く
- 付与したいルートのみヘッダチェック
(FastAPI でも同様にDepends()で切り替え可能)
5. 実装後に必ず押さえる OWASP API Top 10 (2023) の “Broken Authentication” 対策
- 常時 HTTPS(TLS1.2+)
- トークンの短寿命化 + Refresh トークン方式
-
強力なパスワードハッシュ (
bcrypt,argon2) - 多要素認証 (MFA) を UI がある場合は有効化
- レート制限・ブルートフォース検知
- ログと監査証跡を残す(成功/失敗・トークン失効)
- キー/シークレットのローテーション手順を用意
- 自動化テストで「認証なしで呼べるエンドポイント」を検知
- RBAC/スコープ で最小権限原則を徹底
- 外部 SaaS/IAM 連携なら自前実装を最小化して脆弱性を減らす
(詳細は OWASP API Security Top 10 2023 の API2:2023 を参照) (OWASP)
6. 迷ったときの選定ガイド
| 要件 | 推奨方式 |
|---|---|
| モバイル・SPA ログイン | OAuth2 + JWT(Authorization Code + PKCE) |
| サーバ間バッチ | OAuth2 Client Credentials or mTLS |
| 社内マイクロサービス | mTLS + 認可ヘッダ(SPIFFE/SPIRE など) |
| 小規模・社内ツール | 単一 API キー or Basic |
| 公開 API / 他社連携 | OAuth2 / OpenID Connect(外部 IdP 連携) |
まとめ
- 認証方式は「誰が・どう使うか」で決める
- 実装はライブラリに任せ、脆弱な独自実装は避ける
- OWASP API Top 10 を常にチェックし、短寿命トークン+最小権限で運用する
この流れを押さえれば、FastAPI や Hono でも数十行で安全な認証を導入できます。さらに詳しく知りたいフロー(PKCE、mTLS 設定、スコープ設計など)があれば、ぜひ追加で聞いてください。