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/
django-phone-verify handles the complete phone verification flow:
- Send Verification Code - User requests verification, receives SMS with security code
- Verify Code - User submits code, system validates and confirms phone number
- Session Management - Secure JWT-based session tokens prevent tampering
- Multiple Use Cases - Registration, 2FA, password reset, marketing opt-in, and more
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
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]- Add
phone_verifytoINSTALLED_APPS:
INSTALLED_APPS = [
...
"phone_verify",
...
]- Run migrations:
python manage.py migrate- Include the API URLs in your project's
urls.py:
from django.urls import path, include
urlpatterns = [
...
path("api/phone/", include("phone_verify.urls")),
...
]- Configure
PHONE_VERIFICATIONsettings in yoursettings.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,
}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}")Full documentation is available at https://www.sanyamkhurana.com/django-phone-verify/
Quick Links:
- π Getting Started Guide
- βοΈ Configuration Reference
- π Integration Examples
- π Advanced Examples (2FA, password reset, marketing opt-in)
- π§ Custom Backend Guide
- π Security Best Practices
- π API Reference
- π Troubleshooting Guide
- Python 3.8+ (Python 3.7 and below are EOL)
- Django 2.1+
- Django REST Framework 3.9+
Found a bug? Want to suggest an improvement or submit a patch?
We welcome contributions! Here's how you can help:
- π Report bugs via GitHub Issues
- π‘ Suggest features or improvements
- π§ Submit pull requests - please check the contributing guide first
- π 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
This project is licensed under the GPLv3 license.
See the full changelog here: π CHANGELOG.rst