Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Opinionated Django REST auth endpoints for JWT authentication and social accounts

License

Notifications You must be signed in to change notification settings

djangoflow/django-df-auth

Repository files navigation

django-df-auth

This is a simple opinionated module that implements JWT authentication via REST API. For more complex applications please consider using an external authentication service such as https://goauthentik.io

The module is a glue and uses:

  • drf - for the API
  • simplejwt - for JWT
  • pysocial - for social login
  • django-otp* for otp and 2fa
  • twilio - for text messages

The module also provides very limited extra functionality to the packages above:

  • otp devices management OTPDeviceViewSet
    • Create, Delete
  • user registration and invitation methods and template
    • standard User fields = first_name, last_name, email, phone
    • extra User fields / serializer override in settings
  • phone number white/black listing rules (to be removed?) => registration identity blacklist?

Blacklisting:

  • phone / email registration blacklisting (e.g. premium numbers, disposable emails ) regex
  • otp sending blacklisting
  • ip address blacklisting (honey trap)
  • usernames pattern - avoid religiously offensive words

The OTP supports following flows:

  • otp (email/phone/static/totp) verification - can also be used for confirming email/phone
  • 2FA
  • magic signin link

Configuration

Basic Setup

Add to settings.py:

from df_auth.defaults import DF_AUTH_INSTALLED_APPS

INSTALLED_APPS = [
    # ... your apps
    *DF_AUTH_INSTALLED_APPS,
]

AUTHENTICATION_BACKENDS = [
    'df_auth.backends.EmailOTPBackend',
    'df_auth.backends.TwilioSMSOTPBackend',
    'django.contrib.auth.backends.ModelBackend',
    # Optional: social auth backends
    'social_core.backends.google.GoogleOAuth2',
]

Add to urls.py:

urlpatterns = [
    path('api/v1/auth/', include('df_auth.drf.urls')),
]

Registration Flow Configuration

Immediate Account Creation (Default)

By default, accounts are created immediately when users request an OTP:

DF_AUTH = {
    'OTP_AUTO_CREATE_ACCOUNT': True,  # Default
    'SIGNUP_ALLOWED': True,  # Default
}

Flow:

  1. User requests OTP at /auth/otp/ with email/phone
  2. User account created immediately (unverified)
  3. OTP sent to email/phone
  4. User authenticates with OTP to get JWT token
  5. User can confirm device via /auth/otp-devices/{id}/confirm/

Verified Registration Only

To prevent account creation until OTP is confirmed, disable auto-creation:

DF_AUTH = {
    'OTP_AUTO_CREATE_ACCOUNT': False,
    'SIGNUP_ALLOWED': True,
}

Flow:

  1. User must first register via /auth/users/ with email/phone/password
  2. An unconfirmed OTP device is created automatically
  3. User requests OTP via /auth/otp/
  4. User confirms device via /auth/otp-devices/{id}/confirm/
  5. User's email/phone is updated from confirmed device (if OTP_IDENTITY_UPDATE_FIELD=True)

This ensures users must complete the full registration flow before their identity is verified.

Deferred Identity Assignment (Username-only with Email Confirmation)

To allow users to register with a username but defer email/phone assignment until OTP is confirmed:

DF_AUTH = {
    'USER_IDENTITY_FIELDS': {
        'username': 'rest_framework.serializers.CharField',
    },
    'USER_OPTIONAL_FIELDS': {
        'email': 'rest_framework.serializers.CharField',
        'phone_number': 'phonenumber_field.serializerfields.PhoneNumberField',
        'password': 'rest_framework.serializers.CharField',
    },
    'DEFER_IDENTITY_UPDATE': True,  # Defer email/phone until device confirmed
    'OTP_IDENTITY_UPDATE_FIELD': True,  # Update user from confirmed device
}

Flow:

  1. User registers: POST /auth/users/ with { username: "john", email: "[email protected]", password: "..." }
  2. User created with username="john", email="" (blank!) ✅
  3. EmailDevice created with email="[email protected]", confirmed=False
  4. User requests OTP: POST /auth/otp/ with { email: "[email protected]" }
  5. OTP sent to [email protected]
  6. User confirms: POST /auth/otp-devices/{id}/confirm/ with { otp: "123456" }
  7. Device marked confirmed=True
  8. User's email field NOW updated to "[email protected]" ✅

Benefits:

  • Email/phone not saved to user model until verified
  • Multiple users can register with the same unconfirmed email (no uniqueness constraint)
  • Only confirmed email/phone is assigned to the user
  • Prevents spam registrations with disposable emails
  • Username remains the unique identity field

Auto-Send Identity Verification OTP

Automatically send verification OTPs to email/phone when users register:

DF_AUTH = {
    'AUTO_SEND_IDENTITY_VERIFICATION_OTP': True,  # Auto-send OTPs on signup
}

Flow:

  1. User registers: POST /auth/users/ with { email: "[email protected]", password: "..." }
  2. User created with email/phone ✅
  3. EmailDevice/TwilioSMSDevice created with confirmed=False
  4. OTP automatically sent to email/phone
  5. User confirms via /auth/otp-devices/{id}/confirm/ with received OTP ✅
  6. Device marked confirmed=True

Combine with Deferred Identity:

DF_AUTH = {
    'USER_IDENTITY_FIELDS': {'username': '...'},
    'USER_OPTIONAL_FIELDS': {'email': '...', 'phone_number': '...'},
    'DEFER_IDENTITY_UPDATE': True,                      # Don't save until confirmed
    'AUTO_SEND_IDENTITY_VERIFICATION_OTP': True,        # Auto-send OTP
    'OTP_IDENTITY_UPDATE_FIELD': True,                  # Update on confirmation
}

Combined Flow:

  1. User registers with username + email
  2. User created: username="john", email="" (deferred)
  3. Device created with email, OTP automatically sent 📧
  4. User confirms with received OTP
  5. User's email updated to confirmed email ✅

Benefits:

  • Seamless onboarding - users receive OTP immediately
  • No need to manually request OTP via /auth/otp/ endpoint
  • Works with both standard and deferred identity flows
  • Ensures email/phone ownership from registration

Invite-Only Registration

Disable public signups and require authenticated users to invite:

DF_AUTH = {
    'SIGNUP_ALLOWED': False,  # Public signup disabled
    'INVITE_ALLOWED': True,   # Default - authenticated users can invite
}

Flow:

  1. Unauthenticated users cannot POST to /auth/users/
  2. Authenticated users can create invitations via /auth/users/
  3. Created user has UserRegistration.invited_by tracking inviter

OTP Configuration

DF_AUTH = {
    # Update user's email/phone when OTP device is confirmed
    'OTP_IDENTITY_UPDATE_FIELD': True,  # Default

    # Allow OTP requests from non-authenticated users
    'OTP_SEND_UNAUTHORIZED_USER': True,  # Default

    # Available OTP device types
    'OTP_DEVICE_MODELS': {
        'email': 'django_otp.plugins.otp_email.models.EmailDevice',
        'totp': 'django_otp.plugins.otp_totp.models.TOTPDevice',
        'sms': 'otp_twilio.models.TwilioSMSDevice',
    },
}

Identity Field Configuration

Configure which fields uniquely identify users:

DF_AUTH = {
    # Default: email, phone, and username are all identity fields
    'USER_IDENTITY_FIELDS': {
        'username': 'rest_framework.serializers.CharField',
        'email': 'rest_framework.serializers.CharField',
        'phone_number': 'phonenumber_field.serializerfields.PhoneNumberField',
    },
}

Username-only identity (allow duplicate emails/phones):

DF_AUTH = {
    'USER_IDENTITY_FIELDS': {
        'username': 'rest_framework.serializers.CharField',
    },
    'USER_OPTIONAL_FIELDS': {
        'email': 'rest_framework.serializers.CharField',
        'phone_number': 'phonenumber_field.serializerfields.PhoneNumberField',
        'password': 'rest_framework.serializers.CharField',
    },
}

2FA Configuration

2FA is controlled per-user via the User2FA model:

# Enable 2FA for a user
from df_auth.models import User2FA
User2FA.objects.create(user=user, is_required=True)

# Via API
PATCH /api/v1/auth/users/0/two-fa/
{
    "is_required": true
}

When 2FA is enabled:

  • User must provide valid OTP from a confirmed device
  • Works with password auth, social login, and magic links
  • API returns available devices if 2FA required but not provided

Twilio Configuration

Configure Twilio for SMS OTP:

OTP_TWILIO_ACCOUNT = 'your-account-sid'
OTP_TWILIO_AUTH = 'your-auth-token'
OTP_TWILIO_FROM = 'your-twilio-phone-number'
OTP_TWILIO_TOKEN_VALIDITY = 300  # 5 minutes

Social Auth Configuration

Example Google OAuth2 setup:

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = 'your-client-id'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'your-client-secret'

# Fields to populate from social auth
DF_AUTH = {
    'USER_SOCIAL_AUTH_FIELDS': {
        'first_name': 'rest_framework.serializers.CharField',
        'last_name': 'rest_framework.serializers.CharField',
    },
}

API Endpoints

Authentication

  • POST /auth/token/ - Obtain JWT token (username/email/phone + password/otp)
  • POST /auth/token/refresh/ - Refresh JWT token
  • POST /auth/token/verify/ - Verify JWT token
  • POST /auth/token/blacklist/ - Blacklist JWT token

User Management

  • POST /auth/users/ - Register new user or invite user (if authenticated)
  • GET /auth/users/0/ - Get current user profile
  • PATCH /auth/users/0/ - Update user profile
  • POST /auth/users/0/set-password/ - Change password
  • GET /auth/users/0/two-fa/ - Get 2FA status
  • PATCH /auth/users/0/two-fa/ - Update 2FA requirement

OTP

  • POST /auth/otp/ - Request OTP (email or SMS)

OTP Devices

  • GET /auth/otp-devices/ - List user's OTP devices
  • POST /auth/otp-devices/ - Create OTP device (email, sms, totp)
  • GET /auth/otp-devices/{id}/?type={type} - Get device details
  • POST /auth/otp-devices/{id}/confirm/?type={type} - Confirm device with OTP
  • DELETE /auth/otp-devices/{id}/?type={type} - Delete device

Social Authentication

  • POST /auth/social/ - Login with social provider (google-oauth2, facebook, apple)
  • POST /auth/social/connect/ - Connect social account (requires authentication)

About

Opinionated Django REST auth endpoints for JWT authentication and social accounts

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 8

Languages