mcpField
A
auth0-flask

auth0-flask

github.com/auth0セキュリティ55411 回インストール1 日前に更新
リポジトリ

auth0-flask について

auth0-flask は、auth0-server-python を使って Flask Web アプリに Auth0 のログイン、ログアウト、ユーザープロフィールを追加するスキルです。Cookie ベースのセッションと、任意の Redis 利用構成を説明します。

主な機能

  1. 01インタラクティブログインとコールバックを設定
  2. 02プロフィール取得とルート保護
  3. 03アクセストークン取得とログアウト
  4. 04暗号化データを Cookie セッションに保存
  5. 05Redis によるサーバー側セッションを任意設定

活用シーン

  1. 01Flask アプリにログインとログアウトを追加
  2. 02認証が必要なページを保護
  3. 03ユーザープロフィールやアクセストークンを取得
  4. 04セッションデータが Cookie の上限を超える場合に Redis を利用

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/auth0/agent-skills --skill auth0-flask

インストール後、Claude Code で/auth0-flaskを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api.md
integration.md
setup.md
tests/
benchmark-config.json
evals.json
graders.json
package.json
prompt.md
run-evals.mjs

詳細

Auth0 Flask Web アプリ連携

auth0-server-python を使用して、Flask Web アプリケーションにログイン、ログアウト、ユーザープロフィールを追加します。


前提条件

  • Flask アプリケーション
  • Auth0 Regular Web Application の設定(API ではなく、Application である必要があります)
  • まだ Auth0 を設定していない場合は、最初に auth0-quickstart スキルを使用してください

使用しない場合

  • JWT Bearer の検証を行う Python API — FastAPI には auth0-fastapi-api を使用するか、Django REST Framework クイックスタートをご覧ください
  • ログイン/ログアウト UI を備えた FastAPI Web アプリ — 専用のスキルはまだありません。FastAPI クイックスタートをご覧ください
  • シングルページアプリケーション — クライアント側の認証には auth0-react、auth0-vue、または auth0-angular を使用してください
  • Next.js アプリケーション — クライアント側とサーバー側の両方を処理する auth0-nextjs を使用してください
  • Node.js Web アプリ — セッションベースの認証には auth0-express または auth0-fastify を使用してください

クイックスタートのワークフロー

1. SDK をインストールする
pip install auth0-server-python "flask[async]" python-dotenv

重要: flask だけでなく、flask[async] をインストールする必要があります。[async] エクストラは、Flask 2.0 以降で async def ルートハンドラーをサポートするために必要な asgiref をインストールします。これがないと、非同期ルートは動作しません。requirements.txt では、flask[async]>=2.0.0 を使用してください。

2. 環境を設定する

.env を作成します。

AUTH0_DOMAIN=your-tenant.us.auth0.com
AUTH0_CLIENT_ID=your_client_id
AUTH0_CLIENT_SECRET=your_client_secret
AUTH0_SECRET=your_generated_app_secret
AUTH0_REDIRECT_URI=http://localhost:5000/callback

AUTH0_DOMAIN は Auth0 テナントのドメインです(https:// を含めません)。AUTH0_CLIENT_ID と AUTH0_CLIENT_SECRET は、Auth0 Application の設定から取得します。AUTH0_SECRET はセッションデータの暗号化に使用します。openssl rand -hex 64 で生成してください。

3. Auth0 ダッシュボードを設定する

Auth0 Application の設定で、次のようにします。

  • 許可するコールバック URL:http://localhost:5000/callback
  • 許可するログアウト URL:http://localhost:5000
4. 認証モジュールを作成する

Flask のセッションベースのストアを使用して ServerClient を初期化するために、auth.py を作成します。このストアでは Flask 標準の session(デフォルトでは Cookie ベース)を使用するため、外部データベースが不要なステートレス構成になります。

import os
from flask import session as flask_session
from auth0_server_python.auth_server.server_client import ServerClient
from auth0_server_python.auth_types import StateData, TransactionData
from auth0_server_python.store import StateStore, TransactionStore
from dotenv import load_dotenv

load_dotenv()  # Uses .env by default; pass load_dotenv(".env.local") if credentials are in .env.local


class FlaskSessionStateStore(StateStore):
    """State store that uses Flask's session for persistence."""

    def __init__(self, secret: str):
        super().__init__({"secret": secret})

    async def set(self, identifier, state, remove_if_expires=False, options=None):
        data = state.dict() if hasattr(state, "dict") else state
        flask_session[identifier] = self.encrypt(identifier, data)

    async def get(self, identifier, options=None):
        data = flask_session.get(identifier)
        if data is None:
            return None
        decrypted = self.decrypt(identifier, data)
        # Ensure to not return a dict, as the underlying SDK expects a StateData instance, not a dict
        return StateData(**decrypted) if isinstance(decrypted, dict) else decrypted

    async def delete(self, identifier, options=None):
        flask_session.pop(identifier, None)

    async def delete_by_logout_token(self, claims, options=None):
        pass


class FlaskSessionTransactionStore(TransactionStore):
    """Transaction store that uses Flask's session for persistence."""

    def __init__(self, secret: str):
        super().__init__({"secret": secret})

    async def set(self, identifier, state, remove_if_expires=False, options=None):
        data = state.dict() if hasattr(state, "dict") else state
        flask_session[identifier] = self.encrypt(identifier, data)

    async def get(self, identifier, options=None):
        data = flask_session.get(identifier)
        if data is None:
            return None
        decrypted = self.decrypt(identifier, data)
        # Ensure to not return a dict, as the underlying SDK expects a TransactionData instance, not a dict
        return TransactionData(**decrypted) if isinstance(decrypted, dict) else decrypted

    async def delete(self, identifier, options=None):
        flask_session.pop(identifier, None)


secret = os.getenv("AUTH0_SECRET")

auth0 = ServerClient(
    domain=os.getenv("AUTH0_DOMAIN"),
    client_id=os.getenv("AUTH0_CLIENT_ID"),
    client_secret=os.getenv("AUTH0_CLIENT_SECRET"),
    secret=secret,
    redirect_uri=os.getenv("AUTH0_REDIRECT_URI"),
    state_store=FlaskSessionStateStore(secret=secret),
    transaction_store=FlaskSessionTransactionStore(secret=secret),
    authorization_params={"scope": "openid profile email"},
)

ServerClient インスタンスを 1 つ作成し、再利用してください。認証情報をハードコードせず、常に環境変数を使用してください。

仕組み: Flask のデフォルトのセッションは Cookie ベース(ステートレス)です。SDK はセッションデータ(トークン、ユーザープロフィール)をセッションに保存する前に JWE で暗号化するため、データは Cookie 内で署名と暗号化の両方が行われます。サーバー側のデータベースは不要です。

store_options や before_request は不要です: SDK は、store_options(リクエスト/レスポンスオブジェクトなど)をストアメソッドに渡すことをサポートしています。このストアでは flask.session(リクエスト中にグローバルに利用可能)を使用するため、store_options から何かを受け取る必要はなく、SDK メソッドを呼び出す際に渡さずに済みます。flask.session を使わず Cookie を直接管理するカスタムストアを実装する場合は、{"request": request, "response": response} を指定して store_options を再び渡す必要があります。

Cookie サイズに関する注意: ステートレスセッションでは、すべてのデータを Cookie に保存します(上限は約 4KB)。ほとんどのアプリではこれで十分です。大量のセッションデータを保存する場合や、Cookie サイズの上限に達した場合は、ステートフル構成に切り替えてください。

5. Flask アプリを設定する

app.py で、シークレットキーとセッション設定を使用して Flask をセットアップします。

import os
from flask import Flask, redirect, request
from auth import auth0
from dotenv import load_dotenv

load_dotenv()

app = Flask(__name__)
app.secret_key = os.getenv("AUTH0_SECRET")
app.config.update(
    SESSION_COOKIE_SECURE=False,  # Set to True in production (requires HTTPS)
    SESSION_COOKIE_HTTPONLY=True,
    SESSION_COOKIE_SAMESITE="Lax",
)

重要: Flask のセッション管理には app.secret_key の設定が必要です。設定しないと、セッションは動作しません。

本番環境の場合: HTTPS でデプロイするときは SESSION_COOKIE_SECURE=True に設定してください。本番環境で False のままにすると、セッション Cookie が暗号化されていない接続で送信されます。

6. ホームルートを追加する
@app.route("/")
async def home():
    user = await auth0.get_user()
    if user:
        return f"Hello, {user['name']}! <a href='/profile'>Profile</a> | <a href='/logout'>Logout</a>"
    return "Welcome! <a href='/login'>Login</a>"
7. ログインルートを追加する
@app.route("/login")
async def login():
    authorization_url = await auth0.start_interactive_login()
    return redirect(authorization_url)

start_interactive_login() は、Auth0 の Universal Login ページを指す URL 文字列を返します。これを redirect() でラップする必要があります。認可パラメーター(scope、redirect_uri)は、すでに ServerClient で設定されています。

8. コールバックルートを追加する
@app.route("/callback")
async def callback():
    try:
        await auth0.complete_interactive_login(str(request.url))
        return redirect("/")
    except Exception as e:
        return f"Authentication error: {str(e)}", 400

最初の引数として str(request.url) を渡します。これは、認可コードのクエリパラメーターを含む完全なコールバック URL です。トークン交換に失敗する可能性があるため(コードの期限切れや CSRF の不一致など)、必ず try/except で囲んでください。

9. プロフィールルートを追加する(保護対象)
@app.route("/profile")
async def profile():
    user = await auth0.get_user()
    if user is None:
        return redirect("/login")
    return (
        f"<h1>{user['name']}</h1>"
        f"<p>Email: {user['email']}</p>"
        f"<img src='{user['picture']}' alt='{user['name']}' width='100' />"
        f"<p><a href='/logout'>Logout</a></p>"
    )

get_user() は、セッションからユーザーのプロフィールを返します。ログインしていない場合は None を返します。

10. ログアウトルートを追加する
@app.route("/logout")
async def logout():
    url = await auth0.logout()
    return redirect(url)

logout() は Auth0 のログアウト URL を返します。ユーザーをその URL にリダイレクトしてください。

11. アプリをテストする
flask run

http://localhost:5000/login にアクセスして、ログインフローを開始します。


Redis を使ったステートフルなセットアップ

本番アプリや、セッションデータが Cookie のサイズ制限を超える場合は、Flask-Session と Redis を使って、セッションをサーバー側に保存します。Cookie に保存されるのはセッション ID のみです。

1. 依存関係をインストールする
pip install flask-session redis
2. Flask-Session を設定する

Redis をバックエンドとするセッションを使うように app.py を更新します。

import os
from flask import Flask, redirect, request
from flask_session import Session
from auth import auth0
from dotenv import load_dotenv

load_dotenv()

app = Flask(__name__)
app.secret_key = os.getenv("AUTH0_SECRET")
app.config.update(
    SESSION_TYPE="redis",
    SESSION_PERMANENT=True,
    SESSION_KEY_PREFIX="auth0:",
    SESSION_COOKIE_SECURE=False,
    SESSION_COOKIE_HTTPONLY=True,
    SESSION_COOKIE_SAMESITE="Lax",
)
Session(app)
3. ストアの変更は不要

auth.py にある同じ FlaskSessionStateStore と FlaskSessionTransactionStore を、変更せずに使用できます。Flask-Session は flask.session のバックエンドを Cookie から Redis に透過的に切り替えます。ストアは引き続き、これまでどおり flask.session を使用します。

ルートはステートレスなセットアップと同じで、コードを変更する必要はありません。


よくある間違い

間違い修正方法
ソースコードに domain、client_id、client_secret をハードコードする必ず環境変数から読み込み、コードに認証情報を埋め込まないでください
Authlib や python-jose を直接使用する不要です。auth0-server-python がすべての OAuth/OIDC フローを処理します
Flask-Login や Flask-Dance を使用する不要です。SDK がセッションと認証を管理します
jwt.decode() で JWT を手動で解析するSDK がトークンの検証を内部で処理します
[async] extras を付けずに flask をインストールするrequirements.txt では flask[async]>=2.0.0 を使用する必要があります。これがないと、非同期ルートハンドラーはエラーを出さずに失敗します
同期ルートハンドラーを使用するSDK メソッドを呼び出すすべてのルートは async def にし、await を使用する必要があります
app.secret_key の設定を忘れるFlask のセッション管理に必須です。設定しないと、セッションはエラーを出さずに失敗します
Flask で auth0-fastapi-api を使用するこのパッケージは FastAPI API 用です。Flask では auth0-server-python を使用してください
完全な URL(https:// を含む)を domain に渡すdomain には my-tenant.us.auth0.com のようなドメインのみを指定します。https://my-tenant.us.auth0.com ではありません
Auth0 Dashboard でコールバック URL を設定しないAllowed Callback URLs に http://localhost:5000/callback を追加する必要があります
start_interactive_login() をそのまま返すこれはレスポンスではなく URL 文字列を返すため、redirect() でラップする必要があります
/callback でエラーを処理しないcomplete_interactive_login() は失敗する可能性があるため、必ず try/except で囲んでください
await を付けずに SDK メソッドを呼び出すSDK のメソッドはすべて非同期です。await を忘れると、結果ではなくコルーチンが返されます
オプションを位置引数で logout() に渡すlogout(store_options=...) を使用してください。最初の位置引数はストアオプションではなく LogoutOptions です
バックチャネルログアウトが動作すると想定するCookie ベースのセッションではサポートされていません。delete_by_logout_token は何もしません。標準の /logout ルートを使用してください
SESSION_COOKIE_SECURE=False のままデプロイする本番環境では True に設定する必要があります。そうしないと Cookie が HTTP 経由で送信されます

SDK の主なメソッド

すべてのメソッドは非同期です。

メソッドシグネチャ用途
start_interactive_loginawait auth0.start_interactive_login()認証 URL の文字列を返します。redirect() でラップしてください
complete_interactive_loginawait auth0.complete_interactive_login(str(request.url))コールバック URL を処理し、コードをトークンと交換します
get_userawait auth0.get_user()現在のセッションユーザーの辞書、または None を返します
get_access_tokenawait auth0.get_access_token()外部 API の呼び出しに使用するアクセストークンを返します
logoutawait auth0.logout()Auth0 のログアウト URL の文字列を返します

関連スキル

  • auth0-express — ログイン/ログアウトセッションを備えたサーバーサイドレンダリングの Express Web アプリ向け
  • auth0-fastify — セッションベースの認証を備えた Fastify Web アプリケーション向け
  • auth0-cli — ターミナルから Auth0 リソースを管理します

クイックリファレンス

ServerClient の設定:

auth0 = ServerClient(
    domain=os.getenv("AUTH0_DOMAIN"),                    # required
    client_id=os.getenv("AUTH0_CLIENT_ID"),              # required
    client_secret=os.getenv("AUTH0_CLIENT_SECRET"),      # required
    secret=os.getenv("AUTH0_SECRET"),                    # required (encryption secret)
    redirect_uri=os.getenv("AUTH0_REDIRECT_URI"),        # required
    state_store=FlaskSessionStateStore(secret=secret),   # required
    transaction_store=FlaskSessionTransactionStore(secret=secret),  # required
    authorization_params={"scope": "openid profile email"},  # recommended
)

ルート保護のパターン:

user = await auth0.get_user()
if user is None:
    return redirect("/login")

環境変数:

  • AUTH0_DOMAIN — Auth0 テナントのドメイン(例:tenant.us.auth0.com)
  • AUTH0_CLIENT_ID — アプリケーションのクライアント ID
  • AUTH0_CLIENT_SECRET — アプリケーションのクライアントシークレット
  • AUTH0_SECRET — 暗号化とセッション用の秘密鍵
  • AUTH0_REDIRECT_URI — コールバック URL(例:http://localhost:5000/callback)

詳細なドキュメント


参考資料

コメント