👋
Nuxt.jsでWebアプリケーション開発メモ#Tips
JWT
保存方式
- Claude曰くセキュアにするならlocalstorage保存は推奨されない。
- httponlyでCookieに保存する場合は、バックエンドでしかできない。
ペイロード
- 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トークンは不要です。
理由
-
CSRFが必要なケース
- Djangoテンプレートでフォームを使っていた場合、ブラウザは自動でセッションCookieを送信します。
- 外部サイトからユーザーが意図しないPOSTリクエストを送られると、ログイン状態を利用されてしまう可能性があります。
- そのため、サーバーはフォームにCSRFトークンを埋め込み、POST時に照合して正当性を確認していました。
-
JWT + Cookie + 同一オリジンの場合 (現在の構成)
- Cookieに
SameSite=Strict
を設定すると、外部サイトからのリクエストではブラウザがCookieを送信しません。 - そのため、攻撃サイト経由でユーザーのJWTが勝手に送信されることがなく、CSRF攻撃は発生しません。
- さらに
HttpOnly
+Secure
を併用すれば、XSS対策も兼ねられます。
- Cookieに
実装ポイント
- Cookie設定例(Django側)
response.set_cookie(
key="access_token",
value=access_token,
httponly=True,
secure=True,
samesite="Strict",
max_age=300, # 例: 5分
)
Discussion