CuriousLearner/django-phone-verify

A Django app to support phone number verification using security code / One-Time-Password (OTP) sent via SMS.

2fa
django
hacktoberfest
nexmo
one-time-password
otp
phone-number-verification
phone-verification
phone-verification-code
phone-verification-system
sms
twilio

django-phone-verify

image

image

License

image

image

image

image

image

A Django app to support phone number verification using a security code sent via SMS.

django-phone-verify provides a simple, secure way to verify phone numbers for user authentication, 2FA, account recovery, and more. It works seamlessly with Django and Django REST Framework, supports multiple SMS providers (Twilio, Nexmo/Vonage), and is fully extensible with custom backends.

๐Ÿ“– Full Documentation: https://www.sanyamkhurana.com/django-phone-verify/

What It Does

django-phone-verify handles the complete phone verification flow:

  1. Send Verification Code - User requests verification, receives SMS with security code
  2. Verify Code - User submits code, system validates and confirms phone number
  3. Session Management - Secure JWT-based session tokens prevent tampering
  4. Multiple Use Cases - Registration, 2FA, password reset, marketing opt-in, and more

Key Features

Security & Flexibility

  • ๐Ÿ” Secure verification flow - JWT session tokens, configurable code expiration, one-time use options
  • ๐Ÿ”ง Highly customizable - Token length, expiration time, message templates, custom backends
  • ๐Ÿ”’ Production-ready - Rate limiting support, security best practices, GDPR/CCPA compliance guidance

Easy Integration

  • ๐Ÿš€ Django REST Framework - Pre-built viewsets and serializers for instant API setup
  • ๐Ÿ”Œ Pluggable backends - Use Twilio, Nexmo/Vonage, or write your own (AWS SNS, MessageBird, etc.)
  • โœ… Non-intrusive - Works with any AUTH_USER_MODEL, no database changes required to your user model
  • ๐Ÿงช Sandbox mode - Test flows without sending real SMS messages

Multiple Use Cases

  • ๐Ÿ‘ค User registration phone verification
  • ๐Ÿ”‘ Two-factor authentication (2FA)
  • ๐Ÿ”„ Account recovery / password reset
  • ๐Ÿ“ง Marketing opt-in verification
  • ๐Ÿ“ฑ Phone number update flows

Installation

Install the package with all supported backends:

pip install django-phone-verify[all]

Or install with just the backend you need:

pip install django-phone-verify[twilio]
pip install django-phone-verify[nexmo]

Configuration

  1. Add phone_verify to INSTALLED_APPS:
INSTALLED_APPS = [
    ...
    "phone_verify",
    ...
]
  1. Run migrations:
python manage.py migrate
  1. Include the API URLs in your project\'s urls.py:
from django.urls import path, include

urlpatterns = [
    ...
    path("api/phone/", include("phone_verify.urls")),
    ...
]
  1. Configure PHONE_VERIFICATION settings in your settings.py:

For Twilio:

PHONE_VERIFICATION = {
    "BACKEND": "phone_verify.backends.twilio.TwilioBackend",
    "OPTIONS": {
        "SID": "your-twilio-account-sid",
        "SECRET": "your-twilio-auth-token",
        "FROM": "+1234567890",  # Your Twilio phone number
        "SANDBOX_TOKEN": "123456",  # Optional: for testing without sending real SMS
    },
    "TOKEN_LENGTH": 6,
    "MESSAGE": "Welcome to {app}! Please use security code {security_code} to proceed.",
    "APP_NAME": "Phone Verify",
    "SECURITY_CODE_EXPIRATION_TIME": 3600,  # in seconds
    "VERIFY_SECURITY_CODE_ONLY_ONCE": False,
}

For Nexmo (Vonage):

PHONE_VERIFICATION = {
    "BACKEND": "phone_verify.backends.nexmo.NexmoBackend",
    "OPTIONS": {
        "KEY": "your-nexmo-api-key",
        "SECRET": "your-nexmo-api-secret",
        "FROM": "YourApp",  # Sender ID
        "SANDBOX_TOKEN": "123456",  # Optional: for testing
    },
    "TOKEN_LENGTH": 6,
    "MESSAGE": "Welcome to {app}! Please use security code {security_code} to proceed.",
    "APP_NAME": "Phone Verify",
    "SECURITY_CODE_EXPIRATION_TIME": 3600,
    "VERIFY_SECURITY_CODE_ONLY_ONCE": False,
}

Quick Start

Step 1: Send verification code

curl -X POST http://localhost:8000/api/phone/register/ \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+1234567890"}'

# Response:
# {
#   "session_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
#   "phone_number": "+1234567890"
# }

Step 2: Verify the code

curl -X POST http://localhost:8000/api/phone/verify/ \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+1234567890",
    "security_code": "123456",
    "session_token": "eyJ0eXAiOiJKV1QiLCJhbGc..."
  }'

# Response:
# {
#   "message": "Security code is valid",
#   "phone_number": "+1234567890"
# }

Using in Python/Django code:

from phone_verify.services import send_security_code_and_generate_session_token
from phone_verify.services import verify_security_code

# Send verification code via SMS
session_token = send_security_code_and_generate_session_token(
    phone_number="+1234567890"
)
# User receives SMS: "Welcome to Phone Verify! Please use security code 847291 to proceed."

# Verify the code user entered
try:
    verify_security_code(
        phone_number="+1234567890",
        security_code="847291",
        session_token=session_token
    )
    print("โœ“ Phone number verified successfully!")
except Exception as e:
    print(f"โœ— Verification failed: {e}")

Documentation

Full documentation is available at https://www.sanyamkhurana.com/django-phone-verify/

Quick Links:

Compatibility

  • Python 3.8+ (Python 3.7 and below are EOL)
  • Django 2.1+
  • Django REST Framework 3.9+

Contributing

Found a bug? Want to suggest an improvement or submit a patch?

We welcome contributions! Here\'s how you can help:

  1. ๐Ÿ› Report bugs via GitHub Issues
  2. ๐Ÿ’ก Suggest features or improvements
  3. ๐Ÿ”ง Submit pull requests - please check the contributing guide first
  4. ๐Ÿ“– Improve documentation

Before submitting a PR:

  • Write tests for new features
  • Ensure all tests pass: pytest
  • Follow the existing code style
  • Update documentation if needed

License

This project is licensed under the GPLv3 license.

Changelog

See the full changelog here: ๐Ÿ“„ CHANGELOG.rst

Stars
287
1.74% more than last month
Forks
64
Open Issues
8