LoginSignup
1
3

More than 1 year has passed since last update.

[FastAPI] ライブラリを使用したCSRFトークンの実装

Last updated at Posted at 2023-01-13

この記事を読んでできること

CSRFトークンの実装ができる

やりたいこと

ログイン認証機能がないパブリックサイトでクライアントへのCSRFトークンの付与と認証をstarlette-csrfというライブラリで実装する

記述しないこと

  • FastAPIの実装について
  • Cookieについて

使用技術

バックエンド

  • 言語
    • Python 3.10.4
  • フレームワーク
    • Fast API 0.78.0
  • 使用ライブラリ
    • starlette-csrf==1.4.4


トークンを発行して認証するシステムは完全にstarlette-csrfというライブラリに任せます

発行と認証の流れ(フロントとの疎通)

  1. GETメソッドでトークンを発行するAPIをフロントエンドに叩いてもらう
  2. クライアントのCookieファイルにcsrftokenというkeyでランダム文字列のトークンが格納される
  3. リクエスト毎にクライアントからx-csrftokenというkeyでヘッダーを送ってもらう
  4. ライブラリで最初に発行したものと一致するか確認し、問題がなければリクエストを通す

実装例

main.py
import os

from fastapi import FastAPI
from starlette_csrf import CSRFMiddleware

from routers import router


app = FastAPI()

app.add_middleware(
    CSRFMiddleware,
    secret=os.environ["SECRET_KEY"],
)

app.include_router(router.router)
routers/router.py
@router.get("/api/get_csrf_token", tags=["token"])
def get_csrf_token():
    return "トークンを発行しました。"

starlette-csrfについての詳細

starlette-csrfの仕様

  1. 安全なhttpメソッド(GET, HEAD, OPTIONS, TRACE)でリクエストされたとき、set-cookieでクライアントのcookieにcsrftokenというkeyで格納する
  2. クライアントからPOSTリクエストされたとき、x-csrftokenというkeyでcookie headerが送信されることを期待する
  3. cookieとheaderのtokenの値を比較検証する
  4. それらが一致した場合、リクエストは処理される
  5. 一致しない場合は、403 Forbiddenエラー応答が返される

Cookie属性

READMEに詳細記載あり
cookieの名前やパス、Secure属性、Samesite属性を変更することができる

処理の検証結果

  • 現状、単純なapi/get_csrf_tokenというエンドポイントを作成し、tokenをセットする
  • POSTMANで
    • ヘッダにx-csrftokenを用意しない場合は、403エラー
    • ヘッダにx-csrftokenを用意したが、valueが一致しない場合も403エラー
    • ヘッダにx-csrftokenを用意し、valueが一致した場合、リクエストを処理する

参考

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3