Django

Django REST FrameworkでJWT認証を導入する方法 | カスタムユーザモデル対応

ⓘ本ページはプロモーションが含まれています

スポンサードリンク

Introduction: Django REST frameworkでJWT認証を導入する意義

Django REST framework(DRF)におけるJWT認証の導入は、セキュリティと柔軟性の両立が求められる現代のWebアプリケーション開発において不可欠です。特にカスタムユーザモデルを採用することで、企業内システムでは一般的な社員番号(employee_number)フィールドを認証キーとして利用できるため、セキュリティリスクを低減できます。SimpleJWTは、非推奨となったDjango REST framework JWTライブラリに代わる公式サポートされた選択肢であり、トークンのカスタマイズやセキュリティ設定が簡単に行える点で優れています。


SimpleJWTのインストールと基本設定

DRF環境におけるSimpleJWT導入は、最小限の手順で実現可能です。以下にインストールと初期設定を解説します。

インストール手順

  1. 仮想環境アクティベート後、以下のコマンドを実行します。
    bash
    pip install djangorestframework-simplejwt

  2. INSTALLED_APPSrest_framework_simplejwtを追加します。

settings.pyでの設定項目

SimpleJWTのカスタマイズには以下のような設定が必要です。主なオプションはSIMPLE_JWT辞書内に配置されます。

設定項目 値例 内容
ACCESS_TOKEN_LIFETIME datetime.timedelta(minutes=30) 有効期間(アクセストークン)
REFRESH_TOKEN_LIFETIME datetime.timedelta(days=7) 有効期間(リフレッシュトークン)
ALGORITHM 'HS256' シグネチャに使用するアルゴリズム

注意: リフレッシュトークンの有効期限は、セキュリティとユーザーエクスペリエンスを考慮して慎重に設定してください。


カスタムユーザモデルの作成と認証フロー設計

従来のAbstractUserモデルではカバーできない要件(例: 社員番号ベースのログイン)には、カスタムユーザモデルが必須です。以下に実装手順を示します。

AbstractUserからの継承

  1. models.pyAbstractUserを継承したモデルを作成します。
    python
    from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
employee_number = models.CharField(max_length=20, unique=True)

  1. マイグレーションを実行します。
    bash
    python manage.py makemigrations
    python manage.py migrate

社員番号フィールドの認証ロジック

ログイン時に社員番号を優先するため、認証用のget_user_model()関数やサードパーティライブラリのカスタム化が必要です。以下は認証フローの概要です。

  • ユーザーが社員番号・パスワードでログインリクエストを送信
  • 認証処理でemployee_numberpasswordが一致するか検証
  • 成功時、アクセストークンとリフレッシュトークンを発行

トークン発行処理のカスタマイズ

SimpleJWTのデフォルトではメールアドレスベースの認証が実装されているため、社員番号フィールド対応のカスタムが必要です。

TokenObtainPairViewの上書き

  1. serializers.pyに以下のクラスを追加します。
    python
    from rest_framework_simplejwt.views import TokenObtainPairView
    from .models import CustomUser

class CustomTokenObtainPairSerializer(TokenObtainPairView):
def get_user(self, username_field, password):
try:
user = CustomUser.objects.get(**{username_field: username_field})
except CustomUser.DoesNotExist:
raise exceptions.AuthenticationFailed('user not found')
if not user.check_password(password):
raise exceptions.AuthenticationFailed('password mismatch')
return user

custom_claimsの実装

トークンペイロードに社員番号を含めるには、get_tokenメソッドでカスタムします。


認証ミドルウェアの独自実装

認証が確立された後は、リクエストごとにトークンを検証するミドルウェアを実装します。

トークン検証ロジック

  1. middleware.pyに以下のコードを記述します。
    python
    from rest_framework_simplejwt.tokens import RefreshToken, AccessToken

class CustomAuthenticationMiddleware:
def init(self, get_response):
self.get_response = get_response

権限チェックの拡張

特定のAPIにアクセスを制限するには、@permission_classesデコレーターを使用します。


リフレッシュトークンとセキュリティ対策

リフレッシュトークンの使用は、ユーザーがセッション切れでもスムーズにログインし直せる仕組みです。ブラックリスト機能はセキュリティを強化する鍵となります。

RefreshTokenの使い方

  1. リフレッシュトークンを使用してアクセストークンを更新するフローです。
    python
    refresh = RefreshToken(token)
    access_token = str(refresh.access_token)

  2. 有効期間管理(例: 7日が推奨)は、SIMPLE_JWT['REFRESH_TOKEN_LIFETIME']で設定します。

ブラックリスト機能の実装

ブラックリストモデルを追加し、使用済みトークンを登録することで、悪用されたトークンの再利用を防ぎます。


エラーレスポンスのカスタマイズと実装検証

一貫したエラー応答は、開発者と運用チームにとって重要です。以下に具体的な例を示します。

ステータスコードとメッセージの統一

  • 401 Unauthorized: {"error": "認証情報が不正です"}
  • 403 Forbidden: {"error": "権限がありません"}
  • 422 Unprocessable Entity: {"error": "employee_numberまたはpasswordは必須です"}

テストケース例(Postmanで確認)

  1. 正常な認証リクエスト:
  2. URL: /api/token/
  3. Method: POST
  4. Body:
    json
    {
    "employee_number": "E001",
    "password": "secure_password"
    }

  5. レスポンス:
    json
    {
    "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
    }

  6. 無効なトークン送信:

  7. Header: Authorization: Bearer invalid_token
  8. レスポンス:
    json
    {
    "error": "無効なトークンです"
    }

まとめと今後の展望

本記事では、Django REST frameworkにおけるJWT認証の導入方法とカスタマイズ手段について解説しました。特に社員番号を認証キーとして利用する仕組みや、ブラックリストによるセキュリティ強化などの重要なポイントを取り上げました。


  • カスタムユーザモデルの設計と実装
  • SimpleJWTによるトークン発行・検証フローのカスタマイズ
  • 社員番号を用いた認証ロジックの実装
  • リフレッシュトークンとブラックリスト機能の導入
  • 一貫したエラーレスポンス設計

記事で解説したコードをベースに、自身のプロジェクトでJWT認証を導入してみましょう。

スポンサードリンク

-Django