In this tutorial guide, we’ll explore how to implement user authentication in a Django Rest Framework (DRF) project, covering user registration, login (with both username and email), and logout functionality. Authentication is a crucial aspect of web applications to protect user data and ensure a secure user experience. We’ll use DRF’s powerful tools and features to create a robust authentication system. This tutorial can also be used same as it is with MySQL and Postgres. Let’s get started!
Note: For this tutorial, we are using our basic skeleton project for Django. You can also download the project from here.
Step 1. Setting Up Django Rest Framework
Ensure you have Django and DRF installed. If not, you can install them using pip:
pip install django djangorestframework
Next, create a new Django project and app within the project, we usually recommend “accounts” name for authenticaion app.
django-admin startproject mydrfproject
cd mydrfproject
python manage.py startapp accounts
Add ‘rest_framework’, ‘rest_framework.authtoken’, and ‘accounts’ to the INSTALLED_APPS in “mydrfproject/settings.py”:
INSTALLED_APPS = [
# ...
'rest_framework',
'rest_framework.authtoken',
'accounts',
# ...
]
Step 2: Creating the Custom User Model
In “accounts/models.py”, define the custom user model:
# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
# Add custom fields here, if needed
def __str__(self):
return self.username
Update the AUTH_USER_MODEL and REST_FRAMEWORK
default authentication classes in “mydrfproject/settings.py”:
AUTH_USER_MODEL = 'accounts.CustomUser'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
# Other settings...
}
Run migrations to create the custom user model table:
python manage.py makemigrations
python manage.py migrate
Step 3: Serializers for User Authentication
Create serializers.py within the “accounts” app directory:
# accounts/serializers.py
from rest_framework import serializers
from .models import CustomUser
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = ['username', 'email', 'password']
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = CustomUser(
username=validated_data['username'],
email=validated_data['email']
)
user.set_password(validated_data['password'])
user.save()
return user
Step 4: Registering New Users
Create a new API view in “accounts/views.py” for user registration:
# accounts/views.py
from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
from .serializers import UserSerializer
@api_view(['POST'])
def register_user(request):
if request.method == 'POST':
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Step 5: User Login with Authentication Tokens (Username or Email)
In “accounts/views.py”, create a new API view for user login that supports both username and email login:
# accounts/views.py
from rest_framework.authtoken.models import Token
from django.contrib.auth import authenticate
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from django.core.exceptions import ObjectDoesNotExist
from .models import CustomUser
@api_view(['POST'])
def user_login(request):
if request.method == 'POST':
username = request.data.get('username')
password = request.data.get('password')
user = None
if '@' in username:
try:
user = CustomUser.objects.get(email=username)
except ObjectDoesNotExist:
pass
if not user:
user = authenticate(username=username, password=password)
if user:
token, _ = Token.objects.get_or_create(user=user)
return Response({'token': token.key}, status=status.HTTP_200_OK)
return Response({'error': 'Invalid credentials'}, status=status.HTTP_401_UNAUTHORIZED)
Step 6: Implementing User Logout
To handle user logout, we’ll create a new API view in “accounts/views.py”:
# accounts/views.py
from rest_framework.authtoken.models import Token
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def user_logout(request):
if request.method == 'POST':
try:
# Delete the user's token to logout
request.user.auth_token.delete()
return Response({'message': 'Successfully logged out.'}, status=status.HTTP_200_OK)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
Step 7: Wiring Up the URLs
In “accounts/urls.py”, connect the views to URLs:
# accounts/urls.py
from django.urls import path
from .views import register_user, user_login, user_logout
urlpatterns = [
path('register/', register_user, name='register'),
path('login/', user_login, name='login'),
path('logout/', user_logout, name='logout'),
]
Include the “accounts/urls.py” in the project’s main “mydrfproject/urls.py”:
# mydrfproject/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('accounts.urls')), # Include the app's URLs
]
Step 8: Testing the Authentication
To test the authentication endpoints, use cURL or a REST API client like Postman. Here are the example cURL commands:
a. Register a new user:
curl -X POST -H "Content-Type: application/json" -d '{"username": "testuser", "password": "testpassword", "email": "[email protected]"}' http://localhost:8000/api/register/
b. Login with the registered user (using username or email) and get the authentication token:
curl -X POST -H "Content-Type: application/json" -d '{"username": "testuser", "password": "testpassword"}' http://localhost:8000/api/login/
c. Logout using the authentication token:
curl -X POST -H "Authorization: Token YOUR_AUTH_TOKEN" http://localhost:8000/api/logout/
Replace YOUR_AUTH_TOKEN
with the actual authentication token obtained during login.
Conclusion
Congratulations! You’ve successfully implemented user registration, login (supporting both username and email), and logout functionality using Django Rest Framework. By leveraging DRF’s powerful features, you’ve created a secure and user-friendly authentication system for your Django application. Remember to thoroughly test your code and follow best practices to ensure a robust and scalable authentication system. You can further enhance the system by implementing features like email verification, password reset, or social authentication.
Find this tutorial on Github.
Next Tutorial: Reset and Change Password in DRF
Blogs You Might Like to Read!
- Send User Verification and Welcome Email using Django Signals
- Login with OTP via Email/Phone in Django Rest Framework
- Connect and Configure MySQL in Django Project
- Connect and Configure PostgreSQL in Django Project
- Folder and Directory Structure for Django Project: Best Practices
- Django Rest Framework Best Practices for Building Powerful APIs
- Django Best Practices for Building Robust Web Applications