Flask

FlaskでJWT認証とLogto連携:Access/Refreshトークン・RBAC実装ガイド

ⓘ本ページはプロモーションが含まれています

スポンサードリンク

JWT の基本概念と Flask‑JWT‑Extended が提供する機能概要

JSON Web Token(JWT) は「ヘッダー・ペイロード・シグネチャ」の三部構造で、署名されたトークン自体に認可情報を持たせることでステートレスな認証が可能になります。本章では JWT の基礎と、Flask アプリにおける access/refresh トークン管理・カスタムクレーム付与・ブラックリスト機能 を概観します。

Access Token と Refresh Token の違いと活用シーン

トークン種別 推奨有効期限 主な利用シーン
Access Token 5〜15 分 API エンドポイントへの認可チェック
Refresh Token 7 日以上(HTTPS・Secure Cookie が必須) /refresh エンドポイントで新しい Access Token を取得
  • 短命な Access Token は漏洩時の被害範囲を最小化し、長命な Refresh Token は安全に保管すれば再認証不要でトークンローテーションが可能です。
  • トークンは 「すぐに使う」「安全に保管する」 の二軸で設計すると、ユーザー体験とセキュリティの両立が実現します。

カスタムクレーム(role)で実装できるシンプル RBAC

JWT に role クレームを埋め込むだけで、サーバ側はデータベース参照なしにロール判定が行えます。以下は典型的なペイロード例です。

@jwt_required() デコレータで保護したエンドポイント内で get_jwt()["role"] を取得すれば、ロールごとの処理分岐がシンプルに実装できます。

ポイント:トークンは改ざん防止のため署名されているものの、クライアント側でデコード可能です。したがってサーバ側で必ず再チェックし、信頼できない情報として扱うことが重要です。


プロジェクト構成と必須パッケージのインストール方法

このセクションでは 2025 年以降推奨の Flask‑JWT‑Extended 4.xLogto SDK を用いた開発環境を、コードベースから機密情報を分離した形で構築する手順を示します。

仮想環境と依存パッケージのインストール

環境変数で安全に設定する項目

プロジェクトルートに .env を作成し、機密情報は .gitignore に追加 してリポジトリから除外します。

ディレクトリ構成(ベストプラクティス)

この構成は 「設定はコードから分離」「テスト容易性」 を同時に満たし、実務プロジェクトで広く採用されています。


認証エンドポイントでの Access / Refresh Token 発行コード例

認証ロジックは POST /login に集約し、成功時に access_token と refresh_token を JSON 形式で返します。以下ではパスワードハッシュ比較とロール情報(カスタムクレーム)を組み込んだ実装例を示します。

POST /login の実装

  • ポイントcreate_access_tokenadditional_claims を渡すだけでロール情報がトークンに埋め込まれます。
  • ベストプラクティス
  • Access Token は HTTPOnly・Secure Cookie に保存し、JavaScript から直接参照できないようにします。
  • Refresh Token は同様に SameSite=Lax の Secure Cookie として保持し、CSRF 対策を併用してください。

トークン生成ロジックの再利用

この関数はユーザー登録後やパスワードリセット時にも流用でき、コードの重複を防止します。


保護ルート実装と Logto 連携による RBAC の具体的手順

本章では @jwt_required() デコレータで認証済みリクエストを保護しつつ、Logto SDK を利用して最新ロール情報を取得・同期するフローを示します。Logto の API エンドポイントはテナント設定によりパスが変わる可能性があるため、実装時は公式ドキュメントでエンドポイントとレスポンス形式を必ず確認してください。

JWT による認可チェックの基本形

  • get_jwt() が返す辞書に role 配列 があれば、シンプルな Python 条件で認可判断できます。

Logto SDK を用いたロール取得(実装例)

注意:上記エンドポイントは Logto のバージョンやテナント設定に依存します。実装前に GET /api/users/:id/roles が有効か、レスポンスのキー (data, name など) を必ず確認してください。

before_request フックでロールをリアルタイム同期

g.roles に最新ロールを格納すれば、ハンドラ内で if "admin" in g.roles: と書くだけで権限判定が完了します。

デコレータ形式の汎用 RBAC ユーティリティ

エンドポイントごとにロール要件を宣言的に記述でき、コードの可読性が大幅に向上します。


トークンリフレッシュ・失効・エラーハンドリングと最新セキュリティ対策

本節では Refresh Token の安全な使用方法ブラックリスト(ブロックリスト)による即時失効 を実装し、さらに RS256 への移行手順を詳述します。

Refresh Token によるアクセストークン再発行 (POST /refresh)

Flask‑JWT‑Extended 4.x では @jwt_required(refresh=True) が推奨されます。以下は更新エンドポイントの実装例です。

  • ポイント:Refresh Token は @jwt_required(refresh=True) によって保護され、漏洩リスクが低減します。
  • ベストプラクティス:新しい Access Token を生成するたびに Logto からロールを取得すれば、権限変更が即時に反映されます。

Redis を用いたトークンブロックリスト実装(本番向け)

インメモリ set はプロセス終了で消失し、水平スケーリングにも対応できません。以下は Redis に JTI と TTL を保存する永続化ブロックリストのサンプルです。

  • TTL の設定:トークンの有効期限と同じ TTL を付与すれば、Redis のメモリ使用量が自然に削減されます。
  • 水平スケーリング:複数 Flask ワーカー・コンテナから同一 Redis にアクセスできるため、どのインスタンスでも失効状態を即座に参照できます。

RS256 署名アルゴリズムへの移行手順

非対称鍵(RS256)へ切り替えることで、秘密鍵がサーバ側だけに残り、公開鍵は検証用に配布可能 になるため、キー管理の安全性が向上します。

鍵ファイルを環境変数で読み込む例

  • 環境変数でパスを管理すれば、Docker イメージや CI/CD パイプラインに鍵ファイルを埋め込む必要がなく、安全性が保たれます。
  • 本番環境では 権限最小化されたサービスアカウント が鍵ファイルへアクセスできるよう、OS のファイルパーミッションも合わせて設定してください。

統一された JSON エラー形式と Flask の例外ハンドラ

エラーコードは AUTH001~ 系列で統一し、フロントエンド側が簡単にメッセージマッピングできるようにします。

最新セキュリティ対策まとめ

対策 推奨設定例
署名アルゴリズム RS256(公開鍵は PUBLIC_KEY_PATH、秘密鍵は PRIVATE_KEY_PATH
HTTPS 強制 Flask‑Talisman → Talisman(app, force_https=True)
CORS 設定 flask-corsCORS(app, resources={r"/api/*": {"origins": "https://myfrontend.example.com"}})
Cookie セキュリティ set_cookie(..., httponly=True, secure=True, samesite='Lax')
トークン有効期限 Access: 10 分、Refresh: 7 日
ブロックリスト永続化 Redis(TTL=トークン残存時間)

開発・本番導入チェックリスト

  1. 環境変数の確認
  2. PRIVATE_KEY_PATH / PUBLIC_KEY_PATH が正しい PEM ファイルを指すか。
  3. REDIS_URL が本番 Redis インスタンスに接続できるか。

  4. HTTPS・CORS のテスト

  5. ローカルでも mkcert で自己署名証明書を作成し、curl -k https://localhost/api/... が成功すること。
  6. フロントエンドからのリクエストが CORS エラーなく通過するか。

  7. トークンフローの検証(Postman / curl)

  8. /loginaccess_tokenrefresh_token が取得できる。
  9. Authorization: Bearer <access> で保護エンドポイントにアクセスし、期待通りステータスが返る。
  10. /refresh に Refresh Token を送って新しい Access Token が生成される。
  11. /logout 後に同じ Access Token で再度リクエストすると 401 が返る。

  12. Logto ロール同期の確認

  13. 任意ユーザーのロールを Logto コンソールで変更し、即座に /admin のアクセス結果が変わるか。

  14. Redis ブロックリスト動作の確認

  15. 複数ワーカー(Docker Compose で scale)を起動し、どのインスタンスでも logout 後にトークンが失効していること。

まとめ

  • JWT と Flask‑JWT‑Extended を正しく設定すれば、access/refresh の自動管理・カスタムクレーム付与・ブラックリスト機能がシンプルに実装できます。
  • Logto SDK によるロール取得を before_request で同期すれば、権限変更がリアルタイムに反映され、RBAC が安全かつ柔軟になります。
  • RS256 署名Redis 永続化ブロックリスト を導入することで、本番環境でも鍵管理・トークン失効の要件を満たします。
  • エラーハンドリングと統一フォーマットHTTPS/CORS/Cookie のベストプラクティス も併せて実装すれば、全体として堅牢かつ保守しやすい認証基盤が完成します。

このガイドをそのままプロジェクトに組み込めば、数時間で「安全な JWT 認証 + Logto 連携」の最小構成が手に入ります。ぜひ実装・テストを繰り返し、運用上の要件に合わせて微調整してください。

スポンサードリンク

-Flask