Example output
Building a secure and scalable authentication system for an e-commerce platform using Python and Django requires careful attention to project structure, security, and scalability. Here's a detailed guide with source code snippets:
---
### **1. Structuring the Project**
Organize your Django project for modularity and reusability. Use the following structure:
```plaintext
ecommerce_auth/
βββ ecommerce_auth/
β βββ __init__.py
β βββ settings.py
β βββ urls.py
β βββ wsgi.py
βββ authentication/
β βββ __init__.py
β βββ admin.py
β βββ apps.py
β βββ forms.py
β βββ models.py
β βββ serializers.py
β βββ urls.py
β βββ views.py
β βββ utils.py
β βββ tokens.py
β βββ tests.py
β βββ templates/
β βββ registration/
β βββ password_reset_email.html
β βββ password_reset_form.html
βββ manage.py
```
---
### **2. Implementing User Authentication and Authorization**
#### Enable Django's Built-in Authentication
In `settings.py`, configure authentication:
```python
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # For token-based authentication
'authentication', # Custom app
]
AUTH_USER_MODEL = 'authentication.User' # Use a custom user model if needed
# Password validation for security
AUTH_PASSWORD_VALIDATORS = [
{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", "OPTIONS": {"min_length": 8}},
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
],
}
```
---
#### Custom User Model (Optional)
In `models.py`:
```python
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
email = models.EmailField(unique=True)
is_email_verified = models.BooleanField(default=False)
def __str__(self):
return self.username
```
Run migrations:
```bash
python manage.py makemigrations authentication
python manage.py migrate
```
---
#### Registration with Email Verification
In `views.py`:
```python
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .tokens import generate_token
from django.core.mail import send_mail
from django.conf import settings
class RegisterView(APIView):
def post(self, request):
data = request.data
try:
user = User.objects.create(
username=data['username'],
email=data['email'],
password=make_password(data['password']),
)
token = generate_token(user)
send_mail(
'Verify Your Email',
f'Use the link to verify your account: {settings.FRONTEND_URL}/verify/{token}/',
settings.DEFAULT_FROM_EMAIL,
[user.email],
)
return Response({"message": "User registered successfully. Please verify your email."}, status=status.HTTP_201_CREATED)
except Exception as e:
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
```
---
#### Email Token Generation
In `tokens.py`:
```python
from django.contrib.auth.tokens import PasswordResetTokenGenerator
class EmailVerificationTokenGenerator(PasswordResetTokenGenerator):
pass
generate_token = EmailVerificationTokenGenerator()
```
---
### **3. Secure Password Storage and Recovery**
#### Password Reset
In `urls.py`:
```python
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'),
path('password_reset_done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('reset_done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]
```
#### Templates for Password Reset
In `templates/registration/password_reset_email.html`:
```html
<p>Click the link below to reset your password:</p>
<p><a href="{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}">Reset Password</a></p>
```
---
### **4. Session Handling and Token-Based Authentication**
#### Implement JWT
Install `djangorestframework-simplejwt`:
```bash
pip install djangorestframework-simplejwt
```
In `settings.py`:
```python
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}
```
In `urls.py`:
```python
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
urlpatterns += [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
```
---
### **5. Writing Reusable Functions**
In `utils.py`:
```python
from django.core.mail import send_mail
from django.conf import settings
def send_email(subject, message, recipient_list):
send_mail(
subject,
message,
settings.DEFAULT_FROM_EMAIL,
recipient_list,
)
```
---
### **6. Adding Comments and Documentation**
Add comments explaining logic:
```python
class RegisterView(APIView):
"""
Handles user registration.
Sends an email with a verification token upon successful registration.
"""
def post(self, request):
# Extract user data from request
data = request.data
try:
# Create a new user with hashed password
user = User.objects.create(
username=data['username'],
email=data['email'],
password=make_password(data['password']),
)
# Generate email verification token
token = generate_token(user)
# Send verification email
send_email(
'Verify Your Email',
f'Click here to verify: {settings.FRONTEND_URL}/verify/{token}/',
[user.email]
)
return Response({"message": "User registered successfully. Verify your email."}, status=status.HTTP_201_CREATED)
except Exception as e:
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
```
---
### **7. Ensuring Security and Scalability**
1. **Use HTTPS:** Always secure communication with SSL/TLS.
2. **Secure Cookies:** Set `SESSION_COOKIE_SECURE` and `CSRF_COOKIE_SECURE` in `settings.py`.
3. **Rate Limiting:** Use Djangoβs throttling with DRF to prevent brute-force attacks.
4. **Scalability:** Use caching (e.g., Redis) for session storage and consider load balancing.
---
This setup provides a robust foundation for a secure and scalable user authentication system. Let me know if you need help with deployment or additional features!