Migration from dj-rest-auth

This guide helps you migrate from dj-rest-auth to DRF Auth Kit. Both packages provide authentication for Django REST Framework using similar underlying libraries (django-allauth, djangorestframework-simplejwt). DRF Auth Kit offers full type safety, built-in MFA support, accurate OpenAPI schema generation, and more included i18n translations.

Why Migrate?

Advantages of DRF Auth Kit over dj-rest-auth:

  • Full Type Safety: Complete type hints with mypy and pyright compatibility (dj-rest-auth has none)

  • Built-in MFA: Integrated multi-factor authentication with pluggable handlers (email, authenticator apps) - no extra setup required

  • Modern Django Support: Actively maintained with Django 4.2 - 6.x support

  • Accurate OpenAPI Schema: Full DRF Spectacular integration with accurate API documentation

  • Dynamic Configuration: Settings-based customization without subclassing views

  • More i18n Languages: Built-in translations for 57 languages

Quick Comparison

Feature

dj-rest-auth

DRF Auth Kit

Type Hints

None

Full (mypy/pyright)

MFA Support

Requires separate setup

Built-in with pluggable handlers

Social Auth

Auto-generated URLs

Auto-generated URLs

Configuration

Class-based overrides

Settings-based (dynamic imports)

OpenAPI Schema

Partial (via drf-spectacular, less accurate)

Full (accurate schema generation)

i18n Support

Partial (fewer languages)

57 languages included

Migration Steps

Step 1: Update Dependencies

Remove dj-rest-auth and install drf-auth-kit:

# Remove old package
pip uninstall dj-rest-auth

# Install drf-auth-kit (choose one based on your needs)
pip install drf-auth-kit              # Basic authentication
pip install drf-auth-kit[mfa]         # With MFA support
pip install drf-auth-kit[social]      # With social authentication
pip install drf-auth-kit[all]         # All features

Step 2: Update INSTALLED_APPS

Before (dj-rest-auth):

INSTALLED_APPS = [
    # ...
    'rest_framework',
    'rest_framework.authtoken',  # For token auth
    'dj_rest_auth',
    'allauth',
    'allauth.account',
    'dj_rest_auth.registration',  # For registration
    'allauth.socialaccount',      # For social auth
    'allauth.socialaccount.providers.google',
]

After (DRF Auth Kit):

INSTALLED_APPS = [
    # ...
    'rest_framework',
    'allauth',
    'allauth.account',
    'auth_kit',                    # Core authentication
    # Optional: Add these based on your needs
    'auth_kit.mfa',                # For MFA support
    'allauth.socialaccount',       # For social auth
    'allauth.socialaccount.providers.google',
    'auth_kit.social',             # For social auth integration
]

Note

rest_framework.authtoken is only needed if you use AUTH_TYPE = 'token'. For JWT authentication (recommended), it’s not required.

Step 3: Update URL Configuration

Before (dj-rest-auth):

urlpatterns = [
    path('api/auth/', include('dj_rest_auth.urls')),
    path('api/auth/registration/', include('dj_rest_auth.registration.urls')),
    # Social auth (if used)
    path('api/auth/social/', include('allauth.socialaccount.urls')),
]

After (DRF Auth Kit):

urlpatterns = [
    path('api/auth/', include('auth_kit.urls')),
    # Social auth (if used) - automatically generates URLs for all providers
    path('api/auth/social/', include('auth_kit.social.urls')),
]

Note

DRF Auth Kit includes registration endpoints in the main auth_kit.urls pattern. Social URLs are automatically generated for all installed providers.

Step 4: Update Settings

Before (dj-rest-auth):

REST_AUTH = {
    'USE_JWT': True,
    'JWT_AUTH_COOKIE': 'jwt-auth',
    'JWT_AUTH_REFRESH_COOKIE': 'jwt-refresh',
    'JWT_AUTH_HTTPONLY': True,
    'JWT_AUTH_SECURE': False,
    'JWT_AUTH_SAMESITE': 'Lax',
    'SESSION_LOGIN': False,
    'OLD_PASSWORD_FIELD_ENABLED': False,
    'LOGOUT_ON_PASSWORD_CHANGE': False,
    'REGISTER_SERIALIZER': 'myapp.serializers.CustomRegisterSerializer',
    'USER_DETAILS_SERIALIZER': 'myapp.serializers.CustomUserSerializer',
    'LOGIN_SERIALIZER': 'myapp.serializers.CustomLoginSerializer',
}

After (DRF Auth Kit):

AUTH_KIT = {
    # Authentication type (replaces USE_JWT)
    'AUTH_TYPE': 'jwt',             # 'jwt', 'token', or 'custom'
    'USE_AUTH_COOKIE': True,

    # Cookie settings (replaces JWT_AUTH_* settings)
    'AUTH_JWT_COOKIE_NAME': 'auth-jwt',
    'AUTH_JWT_REFRESH_COOKIE_NAME': 'auth-refresh-jwt',
    'AUTH_COOKIE_HTTPONLY': True,
    'AUTH_COOKIE_SECURE': False,    # Set True in production
    'AUTH_COOKIE_SAMESITE': 'Lax',

    # Session and password settings
    'SESSION_LOGIN': False,
    'OLD_PASSWORD_FIELD_ENABLED': False,

    # Custom serializers
    'REGISTER_SERIALIZER': 'myapp.serializers.CustomRegisterSerializer',
    'USER_SERIALIZER': 'myapp.serializers.CustomUserSerializer',
    'LOGIN_REQUEST_SERIALIZER': 'myapp.serializers.CustomLoginSerializer',
}

Settings Mapping Reference:

dj-rest-auth Setting

DRF Auth Kit Setting

USE_JWT

AUTH_TYPE = 'jwt'

JWT_AUTH_COOKIE

AUTH_JWT_COOKIE_NAME

JWT_AUTH_REFRESH_COOKIE

AUTH_JWT_REFRESH_COOKIE_NAME

JWT_AUTH_HTTPONLY

AUTH_COOKIE_HTTPONLY

JWT_AUTH_SECURE

AUTH_COOKIE_SECURE

JWT_AUTH_SAMESITE

AUTH_COOKIE_SAMESITE

JWT_AUTH_COOKIE_DOMAIN

AUTH_COOKIE_DOMAIN

JWT_AUTH_COOKIE_PATH

AUTH_JWT_COOKIE_PATH

JWT_AUTH_REFRESH_COOKIE_PATH

AUTH_JWT_REFRESH_COOKIE_PATH

SESSION_LOGIN

SESSION_LOGIN

OLD_PASSWORD_FIELD_ENABLED

OLD_PASSWORD_FIELD_ENABLED

USER_DETAILS_SERIALIZER

USER_SERIALIZER

LOGIN_SERIALIZER

LOGIN_REQUEST_SERIALIZER

REGISTER_SERIALIZER

REGISTER_SERIALIZER

PASSWORD_RESET_SERIALIZER

PASSWORD_RESET_SERIALIZER

PASSWORD_CHANGE_SERIALIZER

PASSWORD_CHANGE_SERIALIZER

PASSWORD_RESET_CONFIRM_SERIALIZER

PASSWORD_RESET_CONFIRM_SERIALIZER

TOKEN_SERIALIZER

LOGIN_RESPONSE_SERIALIZER (for token auth)

JWT_SERIALIZER

LOGIN_RESPONSE_SERIALIZER (for JWT auth)

TOKEN_CREATOR

JWT_TOKEN_CLAIMS_SERIALIZER (for JWT)

Step 5: Update Authentication Classes

Before (dj-rest-auth with JWT):

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'dj_rest_auth.jwt_auth.JWTCookieAuthentication',
    ],
}

After (DRF Auth Kit):

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'auth_kit.authentication.JWTCookieAuthentication',
    ],
}

Authentication Class Mapping:

dj-rest-auth Class

DRF Auth Kit Class

dj_rest_auth.jwt_auth.JWTCookieAuthentication

auth_kit.authentication.JWTCookieAuthentication

rest_framework.authentication.TokenAuthentication

auth_kit.authentication.TokenCookieAuthentication

Step 6: Update URL Endpoints

Most endpoints have the same paths, but some have changed:

Endpoint Mapping:

dj-rest-auth Endpoint

DRF Auth Kit Endpoint

POST /login/

POST /login/

POST /logout/

POST /logout/

GET /user/

GET /user/

PUT/PATCH /user/

PUT/PATCH /user/

POST /password/change/

POST /password/change/

POST /password/reset/

POST /password/reset/

POST /password/reset/confirm/

POST /password/reset/confirm/

POST /registration/

POST /registration/

POST /registration/verify-email/

POST /registration/verify-email/

POST /registration/resend-email/

POST /registration/resend-email/

POST /token/verify/

POST /token/verify/

POST /token/refresh/

POST /token/refresh/

New Endpoints in DRF Auth Kit (when MFA is enabled):

  • POST /login/verify/ - MFA code verification

  • POST /login/change-method/ - Change MFA method during login

  • POST /login/resend/ - Resend MFA code

  • GET|POST /mfa/ - MFA method management

  • POST /mfa/confirm/ - Confirm MFA method setup

  • POST /mfa/primary/ - Set primary MFA method

  • POST /mfa/deactivate/ - Deactivate MFA method

  • POST /mfa/delete/ - Delete MFA method

  • POST /mfa/send/ - Send MFA verification code

Step 7: Migrate Custom Serializers

If you have custom serializers, update their base classes:

Login Serializer:

# Before (dj-rest-auth)
from dj_rest_auth.serializers import LoginSerializer

class CustomLoginSerializer(LoginSerializer):
    def validate(self, attrs):
        # custom logic
        return super().validate(attrs)

# After (DRF Auth Kit)
from auth_kit.serializers import LoginRequestSerializer

class CustomLoginSerializer(LoginRequestSerializer):
    def validate(self, attrs):
        # custom logic
        return super().validate(attrs)

Registration Serializer:

# Before (dj-rest-auth)
from dj_rest_auth.registration.serializers import RegisterSerializer

class CustomRegisterSerializer(RegisterSerializer):
    first_name = serializers.CharField(required=True)

    def custom_signup(self, request, user):
        user.first_name = self.validated_data.get('first_name', '')
        user.save()

# After (DRF Auth Kit)
from auth_kit.serializers import RegisterSerializer

class CustomRegisterSerializer(RegisterSerializer):
    first_name = serializers.CharField(required=True)

    def custom_signup(self, request, user):
        user.first_name = self.validated_data.get('first_name', '')
        user.save()

User Serializer:

# Before (dj-rest-auth)
from dj_rest_auth.serializers import UserDetailsSerializer

class CustomUserSerializer(UserDetailsSerializer):
    class Meta(UserDetailsSerializer.Meta):
        fields = UserDetailsSerializer.Meta.fields + ('phone_number',)

# After (DRF Auth Kit)
from auth_kit.serializers import UserSerializer

class CustomUserSerializer(UserSerializer):
    class Meta(UserSerializer.Meta):
        fields = UserSerializer.Meta.fields + ('phone_number',)

Password Reset Serializer:

# Before (dj-rest-auth)
from dj_rest_auth.serializers import PasswordResetSerializer

class CustomPasswordResetSerializer(PasswordResetSerializer):
    def get_email_options(self):
        return {'html_email_template_name': 'email/password_reset.html'}

# After (DRF Auth Kit)
from auth_kit.serializers import PasswordResetSerializer

class CustomPasswordResetSerializer(PasswordResetSerializer):
    # DRF Auth Kit uses allauth's email templates directly
    # Configure templates in your allauth settings
    pass

Serializer Class Mapping:

dj-rest-auth Serializer

DRF Auth Kit Serializer

dj_rest_auth.serializers.LoginSerializer

auth_kit.serializers.LoginRequestSerializer

dj_rest_auth.serializers.UserDetailsSerializer

auth_kit.serializers.UserSerializer

dj_rest_auth.serializers.PasswordResetSerializer

auth_kit.serializers.PasswordResetSerializer

dj_rest_auth.serializers.PasswordResetConfirmSerializer

auth_kit.serializers.PasswordResetConfirmSerializer

dj_rest_auth.serializers.PasswordChangeSerializer

auth_kit.serializers.PasswordChangeSerializer

dj_rest_auth.serializers.TokenSerializer

auth_kit.serializers.TokenResponseSerializer

dj_rest_auth.serializers.JWTSerializer

auth_kit.serializers.JWTResponseSerializer

dj_rest_auth.registration.serializers.RegisterSerializer

auth_kit.serializers.RegisterSerializer

Step 8: Migrate Custom Views

If you have custom views, update their base classes:

# Before (dj-rest-auth)
from dj_rest_auth.views import LoginView, LogoutView, UserDetailsView

class CustomLoginView(LoginView):
    def post(self, request, *args, **kwargs):
        # custom logic
        return super().post(request, *args, **kwargs)

# After (DRF Auth Kit)
from auth_kit.views import LoginView, LogoutView, UserView

class CustomLoginView(LoginView):
    def post(self, request, *args, **kwargs):
        # custom logic
        return super().post(request, *args, **kwargs)

Then register your custom views in settings:

AUTH_KIT = {
    'LOGIN_VIEW': 'myapp.views.CustomLoginView',
    'LOGOUT_VIEW': 'myapp.views.CustomLogoutView',
    'USER_VIEW': 'myapp.views.CustomUserView',
}

View Class Mapping:

dj-rest-auth View

DRF Auth Kit View

dj_rest_auth.views.LoginView

auth_kit.views.LoginView

dj_rest_auth.views.LogoutView

auth_kit.views.LogoutView

dj_rest_auth.views.UserDetailsView

auth_kit.views.UserView

dj_rest_auth.views.PasswordChangeView

auth_kit.views.PasswordChangeView

dj_rest_auth.views.PasswordResetView

auth_kit.views.PasswordResetView

dj_rest_auth.views.PasswordResetConfirmView

auth_kit.views.PasswordResetConfirmView

dj_rest_auth.registration.views.RegisterView

auth_kit.views.RegisterView

dj_rest_auth.registration.views.VerifyEmailView

auth_kit.views.VerifyEmailView

dj_rest_auth.jwt_auth.RefreshTokenView

auth_kit.views.RefreshViewWithCookieSupport

Step 9: Migrate Social Authentication

If you’re using social authentication:

Before (dj-rest-auth):

# settings.py
INSTALLED_APPS = [
    # ...
    'dj_rest_auth',
    'dj_rest_auth.registration',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.google',
]

# urls.py
urlpatterns = [
    path('api/auth/', include('dj_rest_auth.urls')),
    path('api/auth/registration/', include('dj_rest_auth.registration.urls')),
    path('api/auth/google/', GoogleLogin.as_view(), name='google_login'),
]

# views.py
from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
from dj_rest_auth.registration.views import SocialLoginView

class GoogleLogin(SocialLoginView):
    adapter_class = GoogleOAuth2Adapter

After (DRF Auth Kit):

# settings.py
INSTALLED_APPS = [
    # ...
    'auth_kit',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.google',
    'auth_kit.social',
]

AUTH_KIT = {
    'SOCIAL_LOGIN_AUTH_TYPE': 'code',  # 'code' or 'token'
    'SOCIAL_LOGIN_AUTO_CONNECT_BY_EMAIL': True,
}

# urls.py - URLs are auto-generated!
urlpatterns = [
    path('api/auth/', include('auth_kit.urls')),
    path('api/auth/social/', include('auth_kit.social.urls')),
]

# No custom view needed! URLs are automatically created:
# POST /api/auth/social/google/ - Login with Google
# POST /api/auth/social/google/connect/ - Connect Google account

Social Authentication Settings Mapping:

dj-rest-auth Pattern

DRF Auth Kit Setting

Custom SocialLoginView subclass

Auto-generated, customize via SOCIAL_LOGIN_VIEW

Custom callback URL handling

SOCIAL_LOGIN_CALLBACK_BASE_URL

Manual URL patterns per provider

Automatic URL generation

Step 10: Run Migrations

After updating your configuration:

python manage.py migrate

Note

If you’re enabling MFA (USE_MFA = True), the migration will create the MFAMethod model. Ensure auth_kit.mfa is in your INSTALLED_APPS before running migrations.

Response Format Changes

Login Response:

The login response format is similar but may have slight differences:

// dj-rest-auth JWT response
{
    "access": "eyJ...",
    "refresh": "eyJ...",
    "user": {
        "pk": 1,
        "username": "user",
        "email": "user@example.com"
    }
}

// DRF Auth Kit JWT response
{
    "access": "eyJ...",
    "refresh": "eyJ...",
    "access_expiration": "2024-01-15T12:00:00Z",
    "refresh_expiration": "2024-01-22T12:00:00Z"
}

If you need user data in the login response, customize the LOGIN_RESPONSE_SERIALIZER.

With MFA enabled, first step returns:

{
    "ephemeral_token": "abc123...",
    "method": {
        "name": "email",
        "is_primary": true
    }
}

Frontend Updates

If your frontend relies on specific response formats, update accordingly:

Token Storage:

  • Cookie names may change (jwt-authauth-jwt by default)

  • Update any JavaScript that references cookie names

Login Flow with MFA:

If you enable MFA, update your frontend to handle the two-step login:

  1. First POST to /api/auth/login/ returns ephemeral_token if MFA is required

  2. Second POST to /api/auth/login/verify/ with ephemeral_token and code

// Example frontend flow
async function login(username, password) {
    const response = await fetch('/api/auth/login/', {
        method: 'POST',
        body: JSON.stringify({ username, password }),
    });
    const data = await response.json();

    if (data.ephemeral_token) {
        // MFA required - show MFA input
        return { requiresMfa: true, ephemeralToken: data.ephemeral_token };
    }
    // No MFA - user is logged in
    return { requiresMfa: false, tokens: data };
}

async function verifyMfa(ephemeralToken, code) {
    const response = await fetch('/api/auth/login/verify/', {
        method: 'POST',
        body: JSON.stringify({ ephemeral_token: ephemeralToken, code }),
    });
    return await response.json();
}

Migration Checklist

Use this checklist to ensure a complete migration:

[ ] Remove dj-rest-auth from requirements
[ ] Install drf-auth-kit with appropriate extras
[ ] Update INSTALLED_APPS
[ ] Update URL configuration
[ ] Convert REST_AUTH settings to AUTH_KIT
[ ] Update authentication classes in REST_FRAMEWORK
[ ] Migrate custom serializers (if any)
[ ] Migrate custom views (if any)
[ ] Update social authentication setup (if used)
[ ] Run migrations
[ ] Update frontend token/cookie handling
[ ] Update frontend for MFA flow (if enabling MFA)
[ ] Test all authentication endpoints
[ ] Update API documentation references

Common Issues

Import Errors:

If you see import errors, ensure you’ve removed all dj_rest_auth imports:

# Find remaining dj_rest_auth imports
grep -r "dj_rest_auth" --include="*.py" .

Cookie Not Being Set:

Check your cookie settings:

AUTH_KIT = {
    'USE_AUTH_COOKIE': True,  # Must be True
    'AUTH_COOKIE_SECURE': False,  # Set False for HTTP (dev only)
    'AUTH_COOKIE_SAMESITE': 'Lax',
}

JWT Token Issues:

Ensure SimpleJWT is configured:

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
}

Social Auth URLs Not Generated:

Ensure the provider apps are in INSTALLED_APPS and configured in SOCIALACCOUNT_PROVIDERS:

INSTALLED_APPS = [
    # ...
    'allauth.socialaccount.providers.google',  # Provider app
    'auth_kit.social',  # Must come after provider apps
]

SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'APP': {
            'client_id': 'your-client-id',
            'secret': 'your-secret',
        }
    }
}

Getting Help