JWT認証・RBAC・トークン失効をライブラリ5個なしで実装する方法【FastAPI vs Fitz比較】
「JWTでログイン機能を作ろう」と思ったら、気づいたら5個もライブラリを入れていた……なんてこと、ありませんか?😅
python-jose、passlib、Redis、自作RBAC……パズルみたいにライブラリを組み合わせていくのは、正直しんどいですよね。そんな課題にズバッと切り込む面白い比較記事が話題になっています。
🔐 本格的なAuth、実は「意外と部品が多い」

「JWT認証」と一口に言っても、実際に本番で使えるレベルにするには、こんなピースが必要になります。
- ✅ パスワードハッシュ(Argon2id推奨。新規プロジェクトでbcryptはもう古い)
- ✅ JWTの署名と検証
- ✅ RBAC(ロールベースアクセス制御):管理者・一般ユーザーの権限管理
- ✅ ログアウト時のトークン失効(ブラックリスト管理)
これをFastAPIで実装しようとすると、自然と python-jose + passlib + Redis + 自作RBACの組み合わせになりがちです。
⚡ FastAPIでの典型的な実装イメージ
ポイントをまとめるとこんな感じです👇
# FastAPI + python-jose + passlib の典型パターン
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta, timezone
SECRET_KEY = "your-secret-key" # 例示用。本番ではコードに直接書かず環境変数などから読み込む
ALGORITHM = "HS256"
# パスワードハッシュ設定(Argon2idを推奨)
pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
# トークン失効用ブラックリスト(本番はRedisに替える)
blacklist: set[str] = set()
app = FastAPI()
# トークンはURLではなくAuthorizationヘッダー(Bearer)から受け取る
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def create_token(data: dict, expires_delta: timedelta = timedelta(minutes=30)):
"""JWTトークンを生成する"""
payload = data.copy()
payload["exp"] = datetime.now(timezone.utc) + expires_delta
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
def verify_token(token: str = Depends(oauth2_scheme)):
"""トークンを検証 + ブラックリストチェック"""
if token in blacklist:
raise HTTPException(status_code=401, detail="トークンは無効化されています")
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload
except JWTError:
raise HTTPException(status_code=401, detail="トークンが不正です")
def require_role(required_role: str):
"""RBACの簡易実装:ロールを確認するデコレータ的な依存関係"""
def checker(payload: dict = Depends(verify_token)):
if payload.get("role") != required_role:
raise HTTPException(status_code=403, detail="権限がありません")
return payload
return checker
@app.get("/admin")
def admin_only(user=Depends(require_role("admin"))):
return {"message": f"ようこそ管理者 {user['sub']} さん!"}
@app.post("/logout")
def logout(token: str = Depends(oauth2_scheme)):
"""トークンをブラックリストに追加してログアウト"""
blacklist.add(token)
return {"message": "ログアウトしました"}
ここが重要です📌
- ブラックリストをメモリ上のsetで管理しているので、本番環境ではRedisに置き換えが必要
- RBACはFastAPIの
Dependsを使って「依存関係として注入」するパターンが主流 - ライブラリが増えるほど、バージョン管理や互換性の維持コストも増える
- FastAPI公式チュートリアルは現在
python-jose+passlibではなくPyJWT+pwdlib[argon2]を使っている。python-joseはアルゴリズム混同の脆弱性(CVE-2024-33663)などが報告されているので、新規実装では公式と同じ構成を検討する
🆚 別解として話題のFitzという言語も知っておこう
今回話題になっているのが、Fitzです。ただし注意点があります。FitzはPythonのライブラリではなく、独自の構文を持つ別のプログラミング言語(Rustベース)で、HTTP・JWT・DB操作などが言語機能として最初から組み込まれています。つまり「FastAPIかFitzか」はPythonプロジェクト内で選べる2択ではなく、そもそも実装言語ごと変える話になる点は誤解しないようにしてください。
とはいえ「認証まわりを何個もライブラリを継ぎ足して実装する」やり方に対して、「最初から一つにまとまった言語・フレームワークを使う」という設計思想自体は、FastAPI流のエコシステム設計と対比する題材として面白い視点です。
📝 まとめ
JWT認証・RBAC・トークンブラックリストを組み合わせた本格的なAuth実装は、FastAPIだと複数ライブラリの連携が必要になりがちです。Fitzのように「言語ごと全部内包」を目指すアプローチも出てきていますが、既存のPythonプロジェクトに導入できるものではない点は押さえておきましょう。
まずはFastAPIで基本的な流れを手を動かして確認してみてください。「むずかしそう」を「できそう」に変える第一歩になるはずです💪 ぜひ試してみてください!
こちらも読まれています
📚 関連商品・おすすめ書籍
※本記事にはアフィリエイトリンクが含まれます。





