django-phone-verify
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:
- 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
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
- 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,
}
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:
- ๐ 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
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:
- ๐ 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
License
This project is licensed under the GPLv3 license.
Changelog
See the full changelog here: ๐ CHANGELOG.rst