FastAPIでのHTTPセッション管理について:(Google OAuth 2.0実装例付き)

FastAPIは高性能なPythonのWeb APIフレームワークですが、セッション管理機能は標準では提供されていません。Flaskのようなシンプルなセッション管理を実現するためには、StarletteのSessionMiddlewareを活用します。

この記事では、FastAPIでSessionMiddlewareを使ってHTTPセッションを管理する方法と、具体的な応用例としてGoogle OAuth 2.0を用いたWebサーバーアプリケーションでの認証フローにおけるセッション管理の実装を紹介します。

FastAPIでのセッション管理

まず、SessionMiddlewareをFastAPIアプリケーションに追加します。

FastAPI自体はStarletteを基盤としているため、Starletteの機能をそのまま使うことが可能です。

from fastapi import FastAPI
from starlette.middleware.sessions import SessionMiddleware

app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="your_secret_key")

SessionMiddlewareは署名付きクッキーを使ってHTTPセッションを実現します。

secret_keyは署名用の秘密鍵で、ランダムな文字列を設定する必要があります。
os.urandom(24).hex()などで生成した値を環境変数経由で読み込むのが一般的です。

セッション変数の設定、取得は以下のように行います。

from fastapi import FastAPI
from starlette.middleware.sessions import SessionMiddleware

app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="your_secret_key")

@app.get("/set_session")
async def set_session(request: Request):
    #セッション変数の設定
    request.session["state"] = "test"
    return 'session data set'

@app.get("/get_session")
async def get_session(request: Request):
   #セッション変数の取得
    var = request.session.get("state")
    return var

Google OAuth 2.0 での活用例

WebアプリケーションでGoogle OAuth 2.0を実装する場合、セッション管理を実装する必要があります。
公式サイトではFlaskでの実装例が載っていますが、ここではGoogleの認証サーバーを利用したログイン機能をFastAPIで実装してみます。

import os
from dotenv import load_dotenv
from fastapi import Request, FastAPI
from fastapi.responses import RedirectResponse
from starlette.middleware.sessions import SessionMiddleware
from google_auth_oauthlib.flow import Flow
load_dotenv()

#クライアントシークレットのパスを環境変数から取得
client_secret = os.getenv('CLIENT_SECRET_PATH')
#セッションの秘密鍵
session_secret_key = os.getenv('SESSION_SECRET_KEY')

# OAuth 2.0 のスコープ (アプリケーションがアクセスを要求するGoogle APIの範囲)
# 今回はGoogle Drive APIへの基本的なアクセス権限をリクエスト
SCOPES = ["https://www.googleapis.com/auth/drive"]

app = FastAPI()

#SessionMiddlewareの定義
app.add_middleware(SessionMiddleware, secret_key= session_secret_key)

@app.get("/login")
async def login(request: Request):
    #OAuth 2.0 flowオブジェクトを作成
    flow = Flow.from_client_secrets_file(
          client_secret, SCOPES
      )
    
    #認証後のリダイレクトURIを指定
    flow.redirect_uri = request.url_for('oauth2callback')

    """
    認証ページのURLとstateを生成
    stateはCSRF(Cross-Site Request Forgery) 攻撃を防ぐために重要
    """
    authorization_url, state = flow.authorization_url(
      access_type= 'offline',
    include_granted_scopes= 'true'
    )

    """
    生成されたstateをセッションに保存
    コールバック時にこのstateを検証する
    """
    request.session['state'] = state

    #ユーザをGoogleの認証ページにリダイレクト
    return RedirectResponse(authorization_url)


@app.get("/oauth2callback")
async def oauth2callback(request: Request):
    """
    認証サーバーからのレスポンスからstateを取得し、事前に生成したstateと比較検証する
    これにより、認証フローが正当なものであることを確認
    """
    state = request.session.get('state')
    flow = Flow.from_client_secrets_file(
      client_secret, scopes=SCOPES, state=state)
    flow.redirect_uri = request.url_for('oauth2callback')

    #認証サーバーからのレスポンスからアクセストークンを取得する
    authorization_response = str(request.url)
    flow.fetch_token(authorization_response=authorization_response)
    creds = flow.credentials
    
    #認証情報をJSON形式でセッションに保存
    request.session["credentials"] = creds.to_json()

    #ログイン成功後、トップページなどにリダイレクト
    return RedirectResponse("/")

@app.get("/")
async def root():
    return {"message": "ログインに成功しました"}

まとめ

FastAPIでのセッション管理は、StarletteのSessionMiddlewareを活用することで実現できます。request.sessionを通じて、ログイン状態や一時的な認証情報などの状態を簡単に保持・参照できます。本記事で紹介したGoogle OAuth 2.0との組み合わせにより、実用的なログイン機能を構築することが可能です。

上記の方法も活用した、自動名刺読み取りアプリも作成していますので、もしよければご覧ください。

参考資料

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする