Skip to main content

Reusable Django OTP Authentication

Project description

Django DRF OTP Auth

PyPI License: MIT

A reusable Django app for email-based One-Time Password (OTP) authentication, designed for Django REST Framework (DRF) and integrated with dj-rest-auth.

Why OTP?

Passwords are a pain. Users forget them, reuse them, and they are a prime target for attackers. Storing them securely is a liability.

Django DRF OTP Auth solves this by eliminating passwords entirely:

  • 🧠 No Memory Required: Users don't need to remember complex passwords.
  • 💾 Zero Password Storage: You don't have to worry about hashing, salting, or leaking passwords.
  • 🔄 Simplified Flows: No more "Forgot Password" or "Reset Password" complexity.
  • 🛡️ Enhanced Security: OTPs are short-lived and one-time use.

Features

  • 🔐 Secure OTP Generation: Cryptographically secure 6-character alphanumeric codes.
  • Cache-Backed: Fast and reliable storage for OTPs with automatic expiration (default 5 minutes).
  • 📧 Email Delivery: Integrated email sending using Django's email backend.
  • 🔌 DRF Integration: Ready-to-use API views for requesting and verifying OTPs.
  • 🎫 JWT Support: Seamlessly integrates with dj-rest-auth to issue JWTs upon verification.
  • ⚙️ Configurable: Customizable project name, email templates, and throttling.
  • 🛡️ Throttling: Built-in support for ScopedRateThrottle to prevent abuse.

Installation

pip install django-drf-otp-auth

Or using uv:

uv add django-drf-otp-auth

Configuration

1. Add to INSTALLED_APPS

Add django_otp_auth to your INSTALLED_APPS in settings.py:

INSTALLED_APPS = [
    ...
    'rest_framework',
    'rest_framework.authtoken',
    'dj_rest_auth',
    'django_otp_auth',
    ...
]

2. Configure REST Framework & Auth

Ensure you have dj-rest-auth and simplejwt configured:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'dj_rest_auth.jwt_auth.JWTCookieAuthentication',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'otp_request': '5/hour',
        'otp_verify': '10/hour',
    }
}

REST_AUTH = {
    'USE_JWT': True,
    'JWT_AUTH_COOKIE': 'access-token',
    'JWT_AUTH_REFRESH_COOKIE': 'refresh-token',
}

3. Email Configuration

Configure your email backend in settings.py:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.example.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'user@example.com'
EMAIL_HOST_PASSWORD = 'password'
DEFAULT_FROM_EMAIL = 'Your App <noreply@example.com>'

4. Optional Settings

Setting Description Default
OTP_AUTH_PROJECT_NAME Project name used in emails 'Lifetivation'
OTP_AUTH_DISABLE_LOCAL_AUTH Enable "Magic OTP" flow (skips email, accepts 000000) False

Local Development (Magic OTP)

To simplify local development and testing, you can enable the "Magic OTP" flow. This allows you to log in as any user using the fixed OTP code 000000, without sending actual emails with the OTP.

  1. Configure the setting in your settings.py to read from an environment variable:
    # Using django-environ
    OTP_AUTH_DISABLE_LOCAL_AUTH = env.bool("OTP_AUTH_DISABLE_LOCAL_AUTH", default=False)
    
  2. Set OTP_AUTH_DISABLE_LOCAL_AUTH=True in your local .env file.
  3. Request an OTP for any email (e.g., test@example.com).
  4. Verify using the code 000000.

[!WARNING] Security Risk: Ensure this environment variable is NEVER set to True in production environments.

Usage

URL Configuration

Include the URLs in your project's urls.py:

from django.urls import path, include
from django_otp_auth.views import RequestOTPView, VerifyOTPView

urlpatterns = [
    # ...
    path('auth/otp/request/', RequestOTPView.as_view(), name='otp_request'),
    path('auth/otp/verify/', VerifyOTPView.as_view(), name='otp_verify'),
    # ...
]

API Endpoints

1. Request OTP

POST /auth/otp/request/

Request a new OTP to be sent to the user's email.

Payload:

{
  "email": "user@example.com"
}

Response:

{
  "message": "OTP sent successfully"
}

2. Verify OTP

POST /auth/otp/verify/

Verify the received OTP. If successful, returns JWT access and refresh tokens (and sets them in cookies if configured).

Payload:

{
  "email": "user@example.com",
  "otp": "ABC123"
}

Response:

{
  "access": "eyJhbGciOiJIUzI1NiIsIn...",
  "user": {
      "pk": 1,
      "email": "user@example.com",
      ...
  }
}

Customization

Email Templates

You can override the email templates by creating the following files in your project's templates directory:

  • templates/emails/otp_email.html
  • templates/emails/otp_email.txt

Context available:

  • otp: The generated OTP code.
  • project_name: The value of OTP_AUTH_PROJECT_NAME.

Development

To run tests locally using uv:

uv run pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_drf_otp_auth-0.1.4.tar.gz (17.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_drf_otp_auth-0.1.4-py3-none-any.whl (7.9 kB view details)

Uploaded Python 3

File details

Details for the file django_drf_otp_auth-0.1.4.tar.gz.

File metadata

  • Download URL: django_drf_otp_auth-0.1.4.tar.gz
  • Upload date:
  • Size: 17.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for django_drf_otp_auth-0.1.4.tar.gz
Algorithm Hash digest
SHA256 91a061a9a49d28be8c9a733c31ecc55df16a17e657df152e3173eb736c59b226
MD5 a88d755762b31e48ea3eb14fbbfe3dae
BLAKE2b-256 3853a0ed8c11a1ef856ef164039625b99c9f7fe4122b8acabe2aec21d568493a

See more details on using hashes here.

File details

Details for the file django_drf_otp_auth-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: django_drf_otp_auth-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 7.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for django_drf_otp_auth-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 a222b6a4070f5618f10ad33b76c9525ea3bd27aa7b65b2ecc50e2b487476f2e7
MD5 01898ebe596256c945a57c0e2930cccb
BLAKE2b-256 c4758299c720ae88ce5da089233264afb3d5ee4eaba9a5e140dbca1646c37853

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page