Implementing Email and Mobile OTP Verification in Django: A Comprehensive Guide

RMAG news

In today’s digital landscape, ensuring the authenticity of user accounts is paramount for web applications. One effective method to achieve this is through email and mobile number verification using One-Time Passwords (OTPs). This article will guide you through the process of implementing OTP verification in a Django project, explaining its importance and providing actionable steps for implementation.

Table of Contents

Introduction
Why OTP Verification Matters
Prerequisites
Step-by-Step Implementation
Best Practices and Considerations
Conclusion

Introduction

One-Time Passwords (OTPs) are unique, temporary codes used to verify a user’s identity. By implementing OTP verification for both email and mobile numbers, you add an extra layer of security to your application, ensuring that users have access to the contact methods they’ve provided.

Why OTP Verification Matters

Enhanced Security: OTP verification significantly reduces the risk of unauthorized access and account takeovers.

User Authentication: It confirms that users have provided valid contact information, which is crucial for account recovery and communication.

Fraud Prevention: It helps prevent the creation of fake accounts, as users must prove ownership of their email and phone number.

Compliance: Many regulatory standards require multi-factor authentication, which OTP verification can help satisfy.

User Trust: Implementing strong security measures like OTP verification builds user confidence in your application.

Prerequisites

Before we begin, make sure you have the following:

Python 3.x installed
Basic knowledge of Django
A Django project set up (if not, we’ll cover that in the steps)

Step-by-Step Implementation

Let’s dive into the process of implementing OTP verification in a Django project.

Step 1: Set up the Django project and app

First, let’s create a new Django project and app:

django-admin startproject otp_verification
cd otp_verification
python manage.py startapp user_auth

Add ‘user_auth’ to INSTALLED_APPS in your project’s settings.py file:

INSTALLED_APPS = [

user_auth,
]

Step 2: Install required packages

We’ll need a couple of additional packages:

pip install django-otp pyotp

Step 3: Create the User model

In your user_auth/models.py file, create a custom user model:

from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
mobile_number = models.CharField(max_length=15, unique=True)
is_email_verified = models.BooleanField(default=False)
is_mobile_verified = models.BooleanField(default=False)
email_otp = models.CharField(max_length=6, null=True, blank=True)
mobile_otp = models.CharField(max_length=6, null=True, blank=True)

Step 4: Create OTP generation and verification functions

Create a new file user_auth/utils.py:

import pyotp
from datetime import datetime, timedelta

def generate_otp():
totp = pyotp.TOTP(pyotp.random_base32(), interval=300) # 5 minutes validity
return totp.now()

def verify_otp(otp, user_otp):
return otp == user_otp

Step 5: Create views for registration and OTP verification

In your user_auth/views.py file:

from django.shortcuts import render, redirect
from django.contrib.auth import login
from .models import CustomUser
from .utils import generate_otp, verify_otp
from django.core.mail import send_mail
from django.conf import settings

def register(request):
if request.method == POST:
username = request.POST[username]
email = request.POST[email]
mobile_number = request.POST[mobile_number]
password = request.POST[password]

user = CustomUser.objects.create_user(username=username, email=email,
mobile_number=mobile_number, password=password)

# Generate and save OTPs
email_otp = generate_otp()
mobile_otp = generate_otp()
user.email_otp = email_otp
user.mobile_otp = mobile_otp
user.save()

# Send email OTP
send_mail(
Email Verification OTP,
fYour OTP for email verification is: {email_otp},
settings.EMAIL_HOST_USER,
[email],
fail_silently=False,
)

# Send mobile OTP (you’ll need to integrate with an SMS service)
# For this example, we’ll just print it
print(fMobile OTP: {mobile_otp})

return redirect(verify_otp, user_id=user.id)

return render(request, register.html)

def verify_otp(request, user_id):
user = CustomUser.objects.get(id=user_id)

if request.method == POST:
email_otp = request.POST[email_otp]
mobile_otp = request.POST[mobile_otp]

if verify_otp(email_otp, user.email_otp) and verify_otp(mobile_otp, user.mobile_otp):
user.is_email_verified = True
user.is_mobile_verified = True
user.email_otp = None
user.mobile_otp = None
user.save()
login(request, user)
return redirect(home)
else:
return render(request, verify_otp.html, {error: Invalid OTP})

return render(request, verify_otp.html)

Step 6: Create URL patterns

In your user_auth/urls.py file:

from django.urls import path
from . import views

urlpatterns = [
path(register/, views.register, name=register),
path(verify_otp/<int:user_id>/, views.verify_otp, name=verify_otp),
]

Don’t forget to include these URLs in your project’s main urls.py file.

Step 7: Create templates

Create two HTML templates in your templates directory:

register.html:

<form method=“post”>
{% csrf_token %}
<input type=“text” name=“username” placeholder=“Username” required>
<input type=“email” name=“email” placeholder=“Email” required>
<input type=“text” name=“mobile_number” placeholder=“Mobile Number” required>
<input type=“password” name=“password” placeholder=“Password” required>
<button type=“submit”>Register</button>
</form>

verify_otp.html:

<form method=“post”>
{% csrf_token %}
<input type=“text” name=“email_otp” placeholder=“Email OTP” required>
<input type=“text” name=“mobile_otp” placeholder=“Mobile OTP” required>
<button type=“submit”>Verify OTP</button>
</form>

Step 8: Configure email settings

In your project’s settings.py file, add the following email configuration:

EMAIL_BACKEND = django.core.mail.backends.smtp.EmailBackend
EMAIL_HOST = smtp.gmail.com # Use your email provider’s SMTP server
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = your_email@gmail.com
EMAIL_HOST_PASSWORD = your_email_password

Replace the placeholder values with your actual email credentials.

Step 9: Run migrations

Apply the database migrations:

python manage.py makemigrations
python manage.py migrate

Step 10: Run the server

Start the Django development server:

python manage.py runserver

Best Practices and Considerations

Security: In a production environment, use more secure methods for storing OTPs, such as hashing them before saving to the database.

SMS Integration: Integrate with a reliable SMS service provider to send mobile OTPs.

OTP Expiry: Implement a mechanism to expire OTPs after a certain time period.

Rate Limiting: Implement rate limiting to prevent abuse of the OTP generation and verification endpoints.

Error Handling: Add robust error handling and user feedback for a smoother user experience.

Resend OTP: Provide an option for users to request a new OTP if they don’t receive the first one.

Progressive Enhancement: Allow users to access limited functionality even if they haven’t verified their contact methods, but require verification for sensitive actions.

Conclusion

Implementing email and mobile OTP verification in your Django application significantly enhances security and user trust. By following this guide, you’ve learned how to set up a basic OTP verification system. Remember to adapt this implementation to your specific needs and always prioritize user data security.

As you continue to develop your application, consider integrating additional security measures and regularly updating your authentication methods to stay ahead of potential threats. With OTP verification in place, you’re taking a crucial step towards building a more secure and trustworthy web application.

Connect with me on my social media platforms for more updates and insights:

Twitter: @rupeshmisra2002

LinkedIn: Rupesh Mishra

GitHub: Rupesh Mishra