👋

Nuxt.jsでWebアプリケーション開発メモ#Tips

に公開

JWT

保存方式

ペイロード

  • DjangoでJWTのペイロードに権限などの情報を含める場合はトークンのカスタムシリアライザーを実装する必要がある。

認証をCookieに含める

  • フロントエンドではfetchする際、credentials: 'include'を使用する。
    • ↑はCSR処理時の指定。
    • SSR処理時はuseRequestHeaders(['cookie'])を使用する。
    • 構文的には両方つけておけばOKのようです。
    • const response = await $fetch<{ user: any }>
        ('http://localhost:8000/api/auth/user/',
        {
          credentials: 'include',
          headers: useRequestHeaders(['cookie']) // SSR時にクッキーを転送
        })
      
  • DjangoではカスタムJWTAuthenticationを実装する。

Nuxt.jsの挙動

middleware(vueファイル内の <script>タグ内のスクリプトも)

SSRで実行される場合(claude codeによる解説)

  • 初回ページアクセス時
  • ページリロード時
  • 直接URL入力時

CSRで実行される場合(claude codeによる解説)

  • navigateTo() でのSPA内遷移時
  • <NuxtLink> クリック時
  • ブラウザの戻る/進むボタン時

実動作を見る限り

  • SSRで実行される場合のケースでもCSRで実行される。
  • useFetchなどは内部でキャッシュしているのでバックエンドへのリクエストは実行されない。
  • ハイドレーション:HTMLに機能を追加(クリック・ソート等)

Nuxt+DRFでのCSRF対策

  • ChatGPTにまとめさせた。
  • 前提として、
    • フロントエンドとバックエンドは同一オリジンで運用する。
    • JWTトークンをhttponly,SameSite=StrictでCookieに保存する。

Nuxt + DRFでJWTをCookie保存する場合のCSRF対策まとめ

Nuxt3 + Django REST Framework(DRF)で、JWTをCookieに保存する場合のCSRF対策について整理します。


結論

同一オリジン + SameSite=Strict でCookie保存している場合、CSRFトークンは不要です。


理由

  1. CSRFが必要なケース

    • Djangoテンプレートでフォームを使っていた場合、ブラウザは自動でセッションCookieを送信します。
    • 外部サイトからユーザーが意図しないPOSTリクエストを送られると、ログイン状態を利用されてしまう可能性があります。
    • そのため、サーバーはフォームにCSRFトークンを埋め込み、POST時に照合して正当性を確認していました。
  2. JWT + Cookie + 同一オリジンの場合 (現在の構成)

    • Cookieに SameSite=Strict を設定すると、外部サイトからのリクエストではブラウザがCookieを送信しません
    • そのため、攻撃サイト経由でユーザーのJWTが勝手に送信されることがなく、CSRF攻撃は発生しません。
    • さらに HttpOnly + Secure を併用すれば、XSS対策も兼ねられます。

実装ポイント

  • Cookie設定例(Django側)
response.set_cookie(
    key="access_token",
    value=access_token,
    httponly=True,
    secure=True,
    samesite="Strict",
    max_age=300,  # 例: 5分
)

Discussion