AI プロンプト
AI プロンプト
AIを使ってAuth0を統合していますか? このプロンプトをCursor、Windsurf、Copilot、Claude Code、またはお気に入りのAI搭載IDEに追加して、開発を効率化しましょう。
Integrate the Auth0 FastAPI SDK into a Python application
AI PERSONA & PRIMARY OBJECTIVE
You are a helpful Auth0 SDK Integration Assistant for Python - FastAPI. Your primary function is to execute commands to set up a development environment for Auth0 with FastAPI. Your secondary function is to modify the files created by those commands.
CRITICAL BEHAVIORAL INSTRUCTIONS
1. CHECK EXISTING PROJECT FIRST: Before creating a new project, check if the current directory already contains a Python project (main.py, requirements.txt, or pyproject.toml). If it does, skip project creation and work with the existing project.
2. EXECUTE FIRST, EDIT SECOND: You MUST first execute the appropriate setup command. Do not show, suggest, or create any files until the setup is complete.
3. NO PLANNING: DO NOT propose a directory structure. DO NOT show a file tree. Your first action must be to run the appropriate command.
4. STRICT SEQUENCE: Follow the "Execution Flow" below in the exact order specified without deviation.
5. BUILD BEAUTIFUL UI: You MUST create a visually appealing, modern login interface with proper styling, animations, and Auth0 branding.
6. 🚨 VIRTUAL ENVIRONMENT RULE: ALWAYS activate the virtual environment before running pip commands.
EXECUTION FLOW
Step 1: Check for Existing Python Project and Prerequisites
FIRST, verify prerequisites and check for existing Python project:
# Pythonとpipがインストールされているかどうかを確認する
python --version && pip --version
Then examine the current directory:
# Check for existing Python project
if [ -f "main.py" ] || [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
echo "Found existing Python project"
ls -la
else
echo "No Python project found, will create new project"
fi
Based on the results:
- If existing project exists, proceed to Step 1b (install Auth0 SDK only)
- If no project exists, proceed to Step 1a (create new project)
Step 1a: Create New Project Directory and Virtual Environment
mkdir auth0-fastapi-app && cd auth0-fastapi-app
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
Step 1b: Install the Auth0 FastAPI SDK and Dependencies
CRITICAL: You MUST install all required packages including itsdangerous:
pip install auth0-fastapi "uvicorn[standard]" python-dotenv itsdangerous
⚠️ IMPORTANT: The square brackets in uvicorn[standard] MUST be quoted to prevent shell glob expansion.
Step 2: Setup Auth0 environment configuration
Step 2.1a: Run Auth0 CLI setup command for your OS:
If MacOS, execute the following command:
AUTH0_APP_NAME="My FastAPI App" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apps create -n "${AUTH0_APP_NAME}" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json > auth0-app-details.json && CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) && CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) && DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && SESSION_SECRET=$(openssl rand -hex 64) && echo "AUTH0_DOMAIN=${DOMAIN}" > .env && echo "AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env && echo "AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env && echo "SESSION_SECRET=${SESSION_SECRET}" >> .env && echo "APP_BASE_URL=http://localhost:3000" >> .env && rm auth0-app-details.json && echo ".env file created with your Auth0 details:" && cat .env
If Windows, execute the following command:
$AppName = "My FastAPI App"; winget install Auth0.CLI; auth0 login --no-input; auth0 apps create -n "$AppName" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json | Set-Content -Path auth0-app-details.json; $ClientId = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_id; $ClientSecret = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_secret; $Domain = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name; $SessionSecret = -join ((1..128) | ForEach {'{0:X}' -f (Get-Random -Max 16)}); Set-Content -Path .env -Value "AUTH0_DOMAIN=$Domain"; Add-Content -Path .env -Value "AUTH0_CLIENT_ID=$ClientId"; Add-Content -Path .env -Value "AUTH0_CLIENT_SECRET=$ClientSecret"; Add-Content -Path .env -Value "SESSION_SECRET=$SessionSecret"; Add-Content -Path .env -Value "APP_BASE_URL=http://localhost:3000"; Remove-Item auth0-app-details.json; Write-Output ".env file created with your Auth0 details:"; Get-Content .env
Step 2.1b: Create manual .env template (if automatic setup fails)
cat > .env << 'EOF'
AUTH0_DOMAIN=your-auth0-domain.auth0.com
AUTH0_CLIENT_ID=your-auth0-client-id
AUTH0_CLIENT_SECRET=your-auth0-client-secret
SESSION_SECRET=$(openssl rand -hex 64)
APP_BASE_URL=http://localhost:3000
EOF
Step 3: Create main.py with Auth0 integration
Replace or create main.py with this complete, production-ready code:
import os
from fastapi import FastAPI, Depends, Request, Response
from fastapi.responses import HTMLResponse
from starlette.middleware.sessions import SessionMiddleware
from dotenv import load_dotenv
from auth0_fastapi.config import Auth0Config
from auth0_fastapi.auth.auth_client import AuthClient
from auth0_fastapi.server.routes import router, register_auth_routes
# Load environment variables
load_dotenv()
app = FastAPI(title="Auth0 FastAPI Example")
# Add Session Middleware - required for cookie handling
app.add_middleware(SessionMiddleware, secret_key=os.getenv("SESSION_SECRET"))
# Create Auth0Config with your Auth0 credentials
config = Auth0Config(
domain=os.getenv("AUTH0_DOMAIN"),
client_id=os.getenv("AUTH0_CLIENT_ID"),
client_secret=os.getenv("AUTH0_CLIENT_SECRET"),
app_base_url=os.getenv("APP_BASE_URL", "http://localhost:3000"),
secret=os.getenv("SESSION_SECRET"),
)
# Instantiate the AuthClient
auth_client = AuthClient(config)
# Attach to the FastAPI app state
app.state.config = config
app.state.auth_client = auth_client
# Register authentication routes
register_auth_routes(router, config)
app.include_router(router)
@app.get("/", response_class=HTMLResponse)
async def home(request: Request, response: Response):
"""Home page with login/logout buttons"""
store_options = {"request": request, "response": response}
session = await auth_client.client.get_session(store_options=store_options)
if session:
user = await auth_client.client.get_user(store_options=store_options)
return f"""
<!DOCTYPE html>
<html>
<head>
<title>Auth0 FastAPI Example</title>
<style>
body {{
font-family: 'Inter', system-ui, -apple-system, sans-serif;
background-color: #1a1e27;
color: #e2e8f0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}}
.container {{
background-color: #262a33;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
padding: 3rem;
max-width: 500px;
width: 90%;
text-align: center;
}}
.logo {{
width: 160px;
margin-bottom: 1.5rem;
}}
h1 {{
font-size: 2.8rem;
font-weight: 700;
color: #f7fafc;
margin-bottom: 1rem;
}}
.success {{
font-size: 1.5rem;
color: #68d391;
font-weight: 600;
margin: 1.5rem 0;
}}
.profile {{
background-color: #2d313c;
border-radius: 15px;
padding: 2rem;
margin: 2rem 0;
}}
.profile-image {{
width: 110px;
height: 110px;
border-radius: 50%;
border: 3px solid #63b3ed;
margin-bottom: 1rem;
}}
.profile-name {{
font-size: 2rem;
font-weight: 600;
color: #f7fafc;
margin-bottom: 0.5rem;
}}
.profile-email {{
font-size: 1.15rem;
color: #a0aec0;
}}
.button {{
padding: 1.1rem 2.8rem;
font-size: 1.2rem;
font-weight: 600;
border-radius: 10px;
border: none;
cursor: pointer;
text-decoration: none;
display: inline-block;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
text-transform: uppercase;
letter-spacing: 0.08em;
}}
.button.logout {{
background-color: #fc8181;
color: #1a1e27;
}}
.button.logout:hover {{
background-color: #e53e3e;
transform: translateY(-5px) scale(1.03);
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
}}
</style>
</head>
<body>
<div class="container">
<img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
alt="Auth0 Logo" class="logo">
<h1>Welcome to Auth0 FastAPI</h1>
<div class="success">✅ Successfully authenticated!</div>
<h2>Your Profile</h2>
<div class="profile">
<img src="{user.get('picture', '')}"
alt="{user.get('name', 'User')}" class="profile-image">
<div class="profile-name">{user.get('name', 'User')}</div>
<div class="profile-email">{user.get('email', '')}</div>
</div>
<a href="/auth/logout" class="button logout">Log Out</a>
</div>
</body>
</html>
"""
else:
return """
<!DOCTYPE html>
<html>
<head>
<title>Auth0 FastAPI Example</title>
<style>
body {{
font-family: 'Inter', system-ui, -apple-system, sans-serif;
background-color: #1a1e27;
color: #e2e8f0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}}
.container {{
background-color: #262a33;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
padding: 3rem;
max-width: 500px;
width: 90%;
text-align: center;
}}
.logo {{
width: 160px;
margin-bottom: 1.5rem;
}}
h1 {{
font-size: 2.8rem;
font-weight: 700;
color: #f7fafc;
margin-bottom: 1rem;
}}
.action-card {{
background-color: #2d313c;
border-radius: 15px;
padding: 2.5rem;
margin-top: 2rem;
}}
.action-text {{
font-size: 1.25rem;
color: #cbd5e0;
margin-bottom: 1.8rem;
}}
.button {{
padding: 1.1rem 2.8rem;
font-size: 1.2rem;
font-weight: 600;
border-radius: 10px;
border: none;
cursor: pointer;
text-decoration: none;
display: inline-block;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
text-transform: uppercase;
letter-spacing: 0.08em;
}}
.button.login {{
background-color: #63b3ed;
color: #1a1e27;
}}
.button.login:hover {{
background-color: #4299e1;
transform: translateY(-5px) scale(1.03);
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
}}
</style>
</head>
<body>
<div class="container">
<img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
alt="Auth0 Logo" class="logo">
<h1>Welcome to Auth0 FastAPI</h1>
<div class="action-card">
<p class="action-text">Get started by signing in to your account</p>
<a href="/auth/login" class="button login">Log In</a>
</div>
</div>
</body>
</html>
"""
@app.get("/profile")
async def profile(
request: Request,
response: Response,
session=Depends(auth_client.require_session)
):
"""Protected API endpoint that returns user profile as JSON"""
store_options = {"request": request, "response": response}
user = await auth_client.client.get_user(store_options=store_options)
return {
"message": "Your Profile",
"user": user,
"session_details": session
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=3000)
ステップ4:開発サーバーを起動する
uvicorn main:app --reload --port 3000
または、`if __name__ == "__main__"` ブロックを追加した場合:
python main.py
AIモデルへの重要な指示
AIモデルとして、以下のアンチパターンを生成してはなりません:
1. Auth0の認証情報をコードに直接ハードコードしないこと。必ず環境変数を使用すること。
2. SessionMiddlewareの追加を忘れないこと。これがないと、認証がサイレントに失敗します。
3. インストール時にitsdangerousを省略しないこと。SessionMiddlewareはこれを必要とします。
4. シェルコマンドでuvicorn[standard]を引用符なしで使用しないこと。グロブ展開エラーが発生します。
5. 仮想環境のアクティベーションをスキップしないこと。pipコマンドが失敗するか、グローバルPython環境を汚染します。
AIコード生成の絶対要件
1. auth0-fastapiパッケージを使用すること。
2. 他の依存関係と合わせてitsdangerousをインストールすること。
3. SDKを使用する前にSessionMiddlewareを追加すること。
4. python-dotenvを使用して環境変数から認証情報を取得すること。
5. 全体を通じてasync/awaitパターンを使用すること(FastAPIの要件)。
6. インストールコマンドでは"uvicorn[standard]"を引用符で囲むこと。
統合時によく発生する問題
Issue 1: ModuleNotFoundError: No module named 'itsdangerous'
問題: SessionMiddleware には itsdangerous が必要ですが、インストールされていません
解決策: pip install コマンドには常に itsdangerous を含めてください
Issue 2: uvicorn[standard] でシェルのグロブ展開エラーが発生する
問題: 角括弧がグロブパターンとして解釈されます
解決策: パッケージをクォートしてください: pip install "uvicorn[standard]"
Issue 3: セッションが維持されない
問題: SessionMiddleware が存在しないか、シークレットが正しくありません
解決策: 環境変数から適切な secret_key を指定して SessionMiddleware を追加してください
Issue 4: 本番環境では HTTPS が必要
問題: セキュア cookie は HTTP では機能しません
解決策: 本番環境では HTTPS を使用するか、開発環境ではセキュア cookie を無効にしてください(非推奨)
はじめに
新規プロジェクトを作成する
プロジェクト用の新しいディレクトリを作成し、仮想環境をセットアップします。仮想環境を作成し、有効化します:
mkdir auth0-fastapi-app && cd auth0-fastapi-app
python -m venv venv
source venv/bin/activate # Windowsの場合: venv\Scripts\activate
Auth0 FastAPI SDKをインストールする
- pip
- Poetry
pip install auth0-fastapi "uvicorn[standard]" python-dotenv itsdangerous
poetry add auth0-fastapi "uvicorn[standard]" python-dotenv itsdangerous
Auth0アプリを設定する
次に、Auth0テナントで新しいアプリを作成し、プロジェクトに環境変数を追加します。CLIコマンドを実行して自動的に行う方法と、Dashboardから手動で行う方法のいずれかを選択できます。
- CLI
- Dashboard
Auth0 アプリを作成して
.env ファイルを生成するには、プロジェクトのルートディレクトリで次のシェルコマンドを実行します。AUTH0_APP_NAME="My FastAPI App" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apps create -n "${AUTH0_APP_NAME}" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json > auth0-app-details.json && CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) && CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) && DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && SESSION_SECRET=$(openssl rand -hex 64) && echo "AUTH0_DOMAIN=${DOMAIN}" > .env && echo "AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env && echo "AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env && echo "SESSION_SECRET=${SESSION_SECRET}" >> .env && echo "APP_BASE_URL=http://localhost:3000" >> .env && rm auth0-app-details.json && echo ".env file created with your Auth0 details:" && cat .env
始める前に、プロジェクトのルートディレクトリに Allowed Logout URLs:許可する Web オリジン:
.env ファイルを作成します。.env
AUTH0_DOMAIN=YOUR_AUTH0_APP_DOMAIN
AUTH0_CLIENT_ID=YOUR_AUTH0_APP_CLIENT_ID
AUTH0_CLIENT_SECRET=YOUR_AUTH0_APP_CLIENT_SECRET
SESSION_SECRET=YOUR_SESSION_SECRET
APP_BASE_URL=http://localhost:3000
- Auth0 Dashboardを開きます
- Applications > Applications > Create Application をクリックします
- ポップアップでアプリの名前を入力し、アプリの種類として
Regular Web Applicationを選択して、Create をクリックします - Application Details ページの Settings タブに切り替えます
.envファイルの値を、Dashboard の ドメイン、クライアントID、クライアントシークレット の値で置き換えますopenssl rand -hex 64を実行してセッションシークレットを生成し、SESSION_SECRETに使用します
http://localhost:3000/auth/callback
http://localhost:3000
http://localhost:3000
Allowed Callback URLs は、認証後にユーザーを安全にアプリケーションへ戻すための重要なセキュリティ対策です。一致する URL がないとログインは失敗し、ユーザーはアプリにアクセスできず、代わりに Auth0 のエラーページが表示されます。Allowed Logout URLs は、サインアウト時にシームレスなユーザー体験を実現するうえで不可欠です。一致する URL がない場合、ユーザーはログアウト後にアプリケーションへリダイレクトされず、代わりに Auth0 の汎用ページにとどまります。Allowed Web Origins は、サイレント認証に不可欠です。これがないと、ユーザーはページを再読み込みしたときや、後でアプリに戻ったときにログアウトされます。
Auth0 FastAPI SDKを設定する
プロジェクトのルートディレクトリに
main.py ファイルを作成し、次のコードを追加してください。main.py
import os
from fastapi import FastAPI, Depends, Request, Response
from starlette.middleware.sessions import SessionMiddleware
from dotenv import load_dotenv
from auth0_fastapi.config import Auth0Config
from auth0_fastapi.auth.auth_client import AuthClient
from auth0_fastapi.server.routes import router, register_auth_routes
# 環境変数を読み込む
load_dotenv()
app = FastAPI(title="Auth0 FastAPI Example")
# セッションミドルウェアを追加する - cookieの処理に必要
app.add_middleware(SessionMiddleware, secret_key=os.getenv("SESSION_SECRET"))
# Auth0の認証情報を使用してAuth0Configを作成する
config = Auth0Config(
domain=os.getenv("AUTH0_DOMAIN"),
client_id=os.getenv("AUTH0_CLIENT_ID"),
client_secret=os.getenv("AUTH0_CLIENT_SECRET"),
app_base_url=os.getenv("APP_BASE_URL", "http://localhost:3000"),
secret=os.getenv("SESSION_SECRET"),
)
# AuthClientをインスタンス化する
auth_client = AuthClient(config)
# FastAPIアプリのstateにアタッチする
app.state.config = config
app.state.auth_client = auth_client
# 認証ルートを登録する
register_auth_routes(router, config)
app.include_router(router)
SESSION_SECRET はセッションクッキーの暗号化に使用されるため、暗号学的に安全である必要があります。十分に強力なシークレット (最低 32 バイト) がないと、アプリケーションのセッションが侵害されるおそれがあります。
openssl rand -hex 64 を使用して安全なシークレットを生成し、バージョン管理にコミットしないでください。SessionMiddleware は、SDK を使用する前に追加する必要があります。これがないと、FastAPI はクッキーを読み書きできず、すべての認証の試行が何のエラーも表示されないまま失敗します。本番環境での HTTPS は、安全なクッキー (secure=True) に必須です。HTTPS がないと、セッションクッキーはブラウザーから送信されず、ユーザーは各リクエストのたびにログアウトされ続けます。ルートを作成し、ユーザープロフィールを表示する
次のルートを これにより以下が作成されます:
main.py ファイルに追加して、ホームページと保護されたプロファイルページを作成します。main.py
import os
from fastapi import FastAPI, Depends, Request, Response
from fastapi.responses import HTMLResponse
from starlette.middleware.sessions import SessionMiddleware
from dotenv import load_dotenv
from auth0_fastapi.config import Auth0Config
from auth0_fastapi.auth.auth_client import AuthClient
from auth0_fastapi.server.routes import router, register_auth_routes
# 環境変数を読み込む
load_dotenv()
app = FastAPI(title="Auth0 FastAPI Example")
# セッションミドルウェアを追加する - cookie処理に必要
app.add_middleware(SessionMiddleware, secret_key=os.getenv("SESSION_SECRET"))
# Auth0の認証情報を使用してAuth0Configを作成する
config = Auth0Config(
domain=os.getenv("AUTH0_DOMAIN"),
client_id=os.getenv("AUTH0_CLIENT_ID"),
client_secret=os.getenv("AUTH0_CLIENT_SECRET"),
app_base_url=os.getenv("APP_BASE_URL", "http://localhost:3000"),
secret=os.getenv("SESSION_SECRET"),
authorization_params={
"scope": "openid profile email", # ユーザープロフィール情報の取得に必要
}
)
# AuthClientをインスタンス化する
auth_client = AuthClient(config)
# FastAPIアプリのstateにアタッチする
app.state.config = config
app.state.auth_client = auth_client
# 認証ルートを登録する
register_auth_routes(router, config)
app.include_router(router)
@app.get("/", response_class=HTMLResponse)
async def home(request: Request, response: Response):
"""Home page with login/logout buttons"""
store_options = {"request": request, "response": response}
session = await auth_client.client.get_session(store_options=store_options)
if session:
user = await auth_client.client.get_user(store_options=store_options)
return f"""
<!DOCTYPE html>
<html>
<head>
<title>Auth0 FastAPI Example</title>
<style>
body {{
font-family: 'Inter', system-ui, -apple-system, sans-serif;
background-color: #1a1e27;
color: #e2e8f0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}}
.container {{
background-color: #262a33;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
padding: 3rem;
max-width: 500px;
width: 90%;
text-align: center;
}}
.logo {{
width: 160px;
margin-bottom: 1.5rem;
}}
h1 {{
font-size: 2.8rem;
font-weight: 700;
color: #f7fafc;
margin-bottom: 1rem;
}}
.success {{
font-size: 1.5rem;
color: #68d391;
font-weight: 600;
margin: 1.5rem 0;
}}
.profile {{
background-color: #2d313c;
border-radius: 15px;
padding: 2rem;
margin: 2rem 0;
}}
.profile-image {{
width: 110px;
height: 110px;
border-radius: 50%;
border: 3px solid #63b3ed;
margin-bottom: 1rem;
}}
.profile-name {{
font-size: 2rem;
font-weight: 600;
color: #f7fafc;
margin-bottom: 0.5rem;
}}
.profile-email {{
font-size: 1.15rem;
color: #a0aec0;
}}
.button {{
padding: 1.1rem 2.8rem;
font-size: 1.2rem;
font-weight: 600;
border-radius: 10px;
border: none;
cursor: pointer;
text-decoration: none;
display: inline-block;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
text-transform: uppercase;
letter-spacing: 0.08em;
}}
.button.logout {{
background-color: #fc8181;
color: #1a1e27;
}}
.button.logout:hover {{
background-color: #e53e3e;
transform: translateY(-5px) scale(1.03);
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
}}
</style>
</head>
<body>
<div class="container">
<img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
alt="Auth0 Logo" class="logo">
<h1>Welcome to Auth0 FastAPI</h1>
<div class="success">✅ Successfully authenticated!</div>
<h2>Your Profile</h2>
<div class="profile">
<img src="{user.get('picture', '')}"
alt="{user.get('name', 'User')}" class="profile-image">
<div class="profile-name">{user.get('name', 'User')}</div>
<div class="profile-email">{user.get('email', '')}</div>
</div>
<a href="/auth/logout" class="button logout">Log Out</a>
</div>
</body>
</html>
"""
else:
return """
<!DOCTYPE html>
<html>
<head>
<title>Auth0 FastAPI Example</title>
<style>
body {
font-family: 'Inter', system-ui, -apple-system, sans-serif;
background-color: #1a1e27;
color: #e2e8f0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}
.container {
background-color: #262a33;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
padding: 3rem;
max-width: 500px;
width: 90%;
text-align: center;
}
.logo {
width: 160px;
margin-bottom: 1.5rem;
}
h1 {
font-size: 2.8rem;
font-weight: 700;
color: #f7fafc;
margin-bottom: 1rem;
}
.action-card {
background-color: #2d313c;
border-radius: 15px;
padding: 2.5rem;
margin-top: 2rem;
}
.action-text {
font-size: 1.25rem;
color: #cbd5e0;
margin-bottom: 1.8rem;
}
.button {
padding: 1.1rem 2.8rem;
font-size: 1.2rem;
font-weight: 600;
border-radius: 10px;
border: none;
cursor: pointer;
text-decoration: none;
display: inline-block;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
text-transform: uppercase;
letter-spacing: 0.08em;
}
.button.login {
background-color: #63b3ed;
color: #1a1e27;
}
.button.login:hover {
background-color: #4299e1;
transform: translateY(-5px) scale(1.03);
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body>
<div class="container">
<img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
alt="Auth0 Logo" class="logo">
<h1>Welcome to Auth0 FastAPI</h1>
<div class="action-card">
<p class="action-text">Get started by signing in to your account</p>
<a href="/auth/login" class="button login">Log In</a>
</div>
</div>
</body>
</html>
"""
@app.get("/profile")
async def profile(
request: Request,
response: Response,
session=Depends(auth_client.require_session)
):
"""Protected API endpoint that returns user profile as JSON"""
store_options = {"request": request, "response": response}
user = await auth_client.client.get_user(store_options=store_options)
return {
"message": "Your Profile",
"user": user,
"session_details": session
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=3000)
- ログアウト時にはログインボタンが表示され、ログイン時にはユーザーのプロファイルが表示されるホームページ (
/) - 認証が必要で、ユーザーデータを JSON として返す保護された API エンドポイント (
/profile) - 洗練されたユーザー体験を実現する充実したスタイリング
チェックポイントこれで、Auth0 のログインページが localhost で正常に動作するようになっているはずです。
高度な使用方法
カスタム依存関係でAPIルートを保護する
カスタム依存関係でAPIルートを保護する
ロールベースアクセス制御用のカスタム FastAPI 依存関係を作成します。
from fastapi import Depends, HTTPException, status
from typing import List
async def require_roles(required_roles: List[str]):
"""ロールベースアクセス制御のための依存関係ファクトリ"""
async def check_roles(
request: Request,
response: Response,
session=Depends(auth_client.require_session)
):
store_options = {"request": request, "response": response}
user = await auth_client.client.get_user(store_options=store_options)
user_roles = user.get("app_metadata", {}).get("roles", [])
if not any(role in user_roles for role in required_roles):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"Required roles: {', '.join(required_roles)}"
)
return session
return check_roles
# ルートでの使用例
@app.get("/admin/dashboard")
async def admin_dashboard(
session=Depends(require_roles(["admin", "superadmin"]))
):
return {"message": "Admin dashboard access granted"}
@app.delete("/admin/users/{user_id}")
async def delete_user(
user_id: str,
session=Depends(require_roles(["admin"]))
):
return {"message": f"User {user_id} deleted"}
アクセストークンを使用した保護されたAPIの呼び出し
アクセストークンを使用した保護されたAPIの呼び出し
API 用のアクセストークンをリクエストするよう SDK を設定し、後続の呼び出しで使用します。
from auth0_fastapi.config import Auth0Config
import httpx
# APIオーディエンスを指定してAuth0を設定
config = Auth0Config(
domain=os.getenv("AUTH0_DOMAIN"),
client_id=os.getenv("AUTH0_CLIENT_ID"),
client_secret=os.getenv("AUTH0_CLIENT_SECRET"),
app_base_url=os.getenv("APP_BASE_URL"),
secret=os.getenv("SESSION_SECRET"),
audience="https://api.example.com", # APIの識別子
authorization_params={
"scope": "openid profile email read:data write:data",
},
)
@app.get("/api/external-data")
async def get_external_data(
request: Request,
response: Response,
session=Depends(auth_client.require_session)
):
"""ユーザーのアクセストークンを使用して外部APIを呼び出す"""
# セッションからアクセストークンを取得
access_token = session.get("access_token")
if not access_token:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="No access token available"
)
# 認証付きのAPI呼び出しを実行
async with httpx.AsyncClient() as client:
api_response = await client.get(
"https://api.example.com/data",
headers={"Authorization": f"Bearer {access_token}"}
)
if api_response.status_code != 200:
raise HTTPException(
status_code=api_response.status_code,
detail="External API call failed"
)
return {"data": api_response.json()}
ステートフルなセッションストレージにRedisを使用する
ステートフルなセッションストレージにRedisを使用する
暗号化されたクッキーではなく Redis にセッションを保存して、アプリケーションをスケールさせます。ステートフルなセッションの利点:
from auth0_fastapi.stores.stateful_state_store import StatefulStateStore
from redis import asyncio as aioredis
# Redisクライアントを作成
redis = await aioredis.from_url(
"redis://localhost:6379",
encoding="utf-8",
decode_responses=True
)
# ステートフルストアを作成
state_store = StatefulStateStore(
secret=os.getenv("SESSION_SECRET"),
store=redis,
cookie_name="_session_id",
expiration=86400, # 秒単位で1日
)
# AuthClientに渡す
auth_client = AuthClient(config, state_store=state_store)
- クッキーサイズの制限なし - 無制限のセッションデータを保存可能
- 即時に無効化可能 - サーバー側でセッションを削除
- バックチャネルログアウトをサポート - Auth0 からのログアウトイベントを処理
- 分散システムに適している - 複数のサーバー間でセッションを共有
トラブルシューティング
セッションが維持されない / ユーザーが何度もログアウトされる
セッションが維持されない / ユーザーが何度もログアウトされる
問題: ユーザーはログインできているものの、リクエストをまたぐとセッションが維持されません。考えられる原因と解決策:
-
SessionMiddleware が追加されていない
アプリに SessionMiddleware を追加していることを確認してください:
from starlette.middleware.sessions import SessionMiddleware app.add_middleware(SessionMiddleware, secret_key=os.getenv("SESSION_SECRET")) -
本番環境で HTTP を使用し、secure cookie が有効になっている
secure cookie を使用するには HTTPS が必要です。ローカルで HTTP を使ってテストしている場合は、一時的に secure cookie を無効にできます (本番環境では非推奨) :
from auth0_fastapi.stores.stateless_state_store import StatelessStateStore state_store = StatelessStateStore( secret=config.secret, cookie_name="_a0_session", expiration=config.session_expiration ) # 開発環境でのみ使用してください! state_store.cookie_options["secure"] = False auth_client = AuthClient(config, state_store=state_store) -
SESSION_SECRET が弱い、または設定されていない
強力なシークレットを生成してください:
openssl rand -hex 64
Auth0 エラー: Callback URL の不一致
Auth0 エラー: Callback URL の不一致
問題: 「Log In」をクリックすると、Auth0 に「Callback URL mismatch」というエラーが表示されます原因: callback URL が Auth0 アプリケーションの設定に登録されていません。解決策:
- Auth0 Dashboard → Applications → Your App → Settings に移動します
- callback URL を Allowed Callback URLs に追加します:
http://localhost:3000/auth/callback - 本番環境では、本番用の URL を追加します:
https://yourdomain.com/auth/callback - Save Changes をクリックします
ImportError または async/await の問題
ImportError または async/await の問題
問題: async 関数やイベントループに関連するエラーが発生します。原因: FastAPI は async フレームワークであり、すべての SDK メソッドは await する必要があります。解決策: すべてのルート関数が async であり、SDK メソッドが正しく await されていることを確認してください:
# ✅ 正しい
@app.get("/profile")
async def profile(request: Request, response: Response):
user = await auth_client.client.get_user(
store_options={"request": request, "response": response}
)
return {"user": user}
# ❌ 誤り - async がない
@app.get("/profile")
def profile(request: Request, response: Response):
user = auth_client.client.get_user(...) # これは失敗します
return {"user": user}
# ❌ 誤り - await がない
@app.get("/profile")
async def profile(request: Request, response: Response):
user = auth_client.client.get_user(...) # データではなく coroutine を返します
return {"user": user}
本番環境では HTTPS が必要
本番環境では HTTPS が必要
問題: ローカルではセッションが機能するのに、本番環境では機能しません。原因: 本番環境で secure cookie を使用するには HTTPS が必要です。
secure=True フラグが設定されていると、暗号化されていない HTTP 接続では cookie が送信されません。解決策:-
HTTPS を設定 します。使用できる方法の例:
- Let’s Encrypt の証明書
- クラウドプロバイダーの SSL/TLS (AWS ALB、Cloudflare など)
- リバースプロキシ (Nginx、Caddy、Traefik)
-
Auth0 アプリケーションの URL を更新 して HTTPS を使用します:
https://yourdomain.com/auth/callback https://yourdomain.com -
APP_BASE_URL で HTTPS を使用していることを確認 します:
APP_BASE_URL=https://yourdomain.com