Django and Firebase Integration for Seamless User Authentication

Introduction

Authentication is an essential aspect of any web application, and it is crucial to ensure user data security. Django, a popular web framework comes with built-in authentication capabilities and allows developers to implement custom authentication methods. In this blog post, we will explore how to implement Firebase email/password authentication in Django custom authentication.

Firebase is a mobile and web application development platform that offers a wide range of features, including authentication, databases, storage, and more. Firebase’s authentication service ensures both security and user-friendliness. It offers a range of authentication methods, among them the straightforward email/password combination. By integrating Firebase authentication into Django, developers, often referred to as Firebase developers, can leverage Firebase’s benefits while still using Django’s powerful web development features.

This integration allows Firebase developers to combine the authentication simplicity of Firebase with Django’s robust capabilities, creating a seamless user experience while maintaining the flexibility to implement complex functionalities. With Firebase’s real-time updates and Django’s versatile framework, Firebase developers can craft applications that are both dynamic and feature-rich, catering to the modern demands of users in today’s fast-paced digital landscape.

Firebase Introduction

Firebase authentication is one of Firebase’s many services. It provides secure and easy-to-use authentication services, allowing developers to authenticate users using various methods, such as email/password, phone number, social media, and more. Firebase authentication provides a simple API that can be used in any client-side or server-side environment.

Firebase email/password authentication is a straightforward and secure method of authenticating users using their email addresses and passwords. It is an ideal method for apps that don’t require additional identity providers or social media integrations. Firebase email/password authentication provides features such as email verification, password reset, and account deletion, making it a robust authentication solution for web and mobile applications.

Related read: What is Firebase: The Good and the Bad of Firebase Backend Services

Prerequisites

Before you embark on integrating Firebase Admin with Django, there are certain prerequisites that developers should ensure are in place.

prerequisites for firebase authentication integration

➡️ Firebase Account: Developers need to create a Firebase account and create a project in the Firebase Console. This project will configure Firebase authentication and other Firebase services used in the Django application.

➡️ Python and Django: Developers should understand Python and the Django web framework. Django is a popular Python web framework, used to build web applications, including Firebase ones.

➡️ Firebase Admin SDK: Developers need to install and configure the Firebase Admin SDK for Python. The Firebase Admin SDK provides APIs for Firebase services that can be used on the server side of the application.

➡️ Firebase Authentication: Developers need to enable Firebase authentication for their project in the Firebase Console. This will allow them to authenticate users in their Django application using Firebase’s authentication service.

➡️ Django Rest Framework: If building a RESTful API, developers should understand Django Rest Framework. This framework allows developers to build APIs quickly and easily using Django.

By having these prerequisites in place, developers can integrate Firebase Admin and Django easily, ensuring a robust and secure authentication solution for their web applications.

Implementation

Step 1: The first step is to install Django and DRF. You can do this using pip, Python’s package manager.

Open your command prompt or terminal and type the following command:

pip install django djangorestframework firebase-admin

This will install the latest version of Django and DRF on your system.

Step 2: Create a Django project: After installing Django and DRF, the next step is to create a Django project. Django projects are collections of settings and configurations for a specific website or web application.

To create your Django project, navigate to the directory where you want to create your project and type the following command:

django-admin startproject firebase_auth_django

This will create an entire directory called firebase_auth_django, which contains all the necessary files and directories for your Django project.

Step 3: Create a Django app: A Django app is a component of a Django project that performs specific functionality. You can create multiple apps within a Django project.

To create an app, navigate to the root directory of your project and type the following command:

python manage.py startapp users

This will create a newly created directory called users, which contains the necessary files for your Django app.

Step 4: Set up Firebase in the Django project: We need to create a Firebase project in the Firebase Console and obtain the Firebase Admin SDK credentials, which include the service account key. Once we have the service account key, we can set up Firebase in the Django project using the following code:

import os
import json
import requests
import firebase_admin
import firebase_admin.auth as auth
from firebase_admin import credentials
from rest_framework import authentication


cred = credentials.Certificate("static/fir-auth-with-django-firebase-adminsdk-1zepn-3023fd129c.json")
firebase_admin.initialize_app(cred)
FIREBASE_WEB_API_KEY = os.environ.get("FIREBASE_WEB_API_KEY")
rest_api_url = f"https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword"


def create_user(email, password):
"""
Function for creating firebase user.
"""
created_user = auth.create_user(email=email, password=password)
return created_user.uid


def change_firebase_user_password(new_password, uid):
"""
Function for changing password of firebase user.
"""
auth.update_user(uid, password=new_password)


def change_firebase_user_email(uid, new_email):
"""
Function for change email of firebase user.
"""
auth.update_user(uid, email=new_email)


def delete_firebase_user(uid):
"""
Function for deleting firebase user.
"""
auth.delete_user(uid)


def login_firebase_user(email, password):
"""
Function for login firebase user.
"""
payload = json.dumps({
"email": email,
"password": password,
"returnSecureToken": True
})

r = requests.post(rest_api_url,
params={"key": FIREBASE_WEB_API_KEY},
data=payload)
return r.json()


def logout_firebase_user(uid):
auth.revoke_refresh_tokens(uid)


class FirebaseAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
from users.models import CustomUser
token = request.headers.get('Authorization')
if not token:
return None

try:
token = token.split(" ")[1]
decoded_token = auth.verify_id_token(token, check_revoked=True)
uid = decoded_token["uid"]
except:
return None

try:
user = CustomUser.objects.get(uid=uid)
return user, None

except CustomUser.DoesNotExist:
return None

def get_user(self, user_id):
from users.models import CustomUser
try:
return CustomUser.objects.get(id=user_id)
except CustomUser.DoesNotExist:
return None

Step 5: Configure Django settings according to the Firebase and Rest Framework:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

'rest_framework',
'django_filters',

'users'
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTIACTION_CLASSES': (
'utilities.firebase.FirebaseAuthentication',
),
'DEFAULT_FILTER_BACKENDS':
('django_filters.rest_framework.DjangoFilterBackend',),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
'EXCEPTION_HANDLER': 'utilities.utils.custom_exception_handler',
}

Step 6: Implement login and logout: We need to create views in Django to handle user login and logout. These views will use Firebase authentication APIs to authenticate and manage user accounts. Here’s an example of a view for user registration:

from rest_framework import status
from rest_framework.response import Response
from rest_framework.generics import (
CreateAPIView,
RetrieveAPIView,
)
from rest_framework.permissions import IsAuthenticated

from .models import CustomUser
from utilities import messages
from .serializers import LoginSerializer
from utilities.utils import ResponseInfo
from utilities.firebase import (
login_firebase_user,
logout_firebase_user,
FirebaseAuthentication,
)


class LoginAPIView(CreateAPIView):
"""
Class for creating api for login user.
"""
permission_classes = ()
authentication_classes = ()
serializer_class = LoginSerializer

def __init__(self, **kwargs):
"""
Constructor function for formatting the web response to return.
"""
self.response_format = ResponseInfo().response
super(LoginAPIView, self).__init__(**kwargs)

def post(self, request, *args, **kwargs):
"""
POST Method for login users.
"""
try:
CustomUser.objects.get(email=request.data["email"])
serializer = self.get_serializer(data=request.data)

if serializer.is_valid(raise_exception=True):
user = login_firebase_user(serializer.validated_data.pop("email"), serializer.validated_data.pop('password'))
if not user.get("error"):
self.response_format["data"] = user
self.response_format["message"] = [messages.SUCCESS]
else:
self.response_format["status_code"] = status.HTTP_400_BAD_REQUEST
self.response_format["error"] = "login_error"
self.response_format["message"] = [messages.INVALID_CREDENTIALS]
except CustomUser.DoesNotExist:
self.response_format["data"] = None
self.response_format["error"] = "user"
self.response_format["status_code"] = status.HTTP_404_NOT_FOUND
self.response_format["message"] = [messages.UNAUTHORIZED_ACCOUNT]
return Response(self.response_format)


class LogoutAPIView(CreateAPIView):
"""
Class for creating api for logout user.
"""
permission_classes = (IsAuthenticated,)
authentication_classes = (FirebaseAuthentication,)
serializer_class = LoginSerializer

def __init__(self, **kwargs):
"""
Constructor function for formatting the web response to return.
"""
self.response_format = ResponseInfo().response
super(LogoutAPIView, self).__init__(**kwargs)

def post(self, request, *args, **kwargs):
"""
POST Method for logout users.
"""
uid = request.user.uid
logout_firebase_user(uid)

self.response_format["data"] = None
self.response_format["error"] = None
self.response_format["status_code"] = status.HTTP_200_OK
self.response_format["message"] = [messages.LOGOUT_SUCCESS]
return Response(self.response_format)

Step 7: Now we are at the final stage of this blog, we will create an API that allows only authenticated users to access it.

class GetDataAPIView(RetrieveAPIView):
"""
Class for creating api for getting authenticated data.
"""
permission_classes = (IsAuthenticated,)
authentication_classes = (FirebaseAuthentication,)
serializer_class = LoginSerializer

def __init__(self, **kwargs):
"""
Constructor function for formatting the web response to return.
"""
self.response_format = ResponseInfo().response
super(GetDataAPIView, self).__init__(**kwargs)

def get(self, request, *args, **kwargs):
"""
GET Method for getting authenticated data.
"""
self.response_format["data"] = request.user.email
return Response(self.response_format)

By following these steps, we can easily implement Firebase email/password authentication in Django and ensure a robust and secure authentication solution for our web applications.

Related read: Firebase Authentication & Email Verification In Android

coma

Conclusion

In conclusion, implementing Firebase email/password authentication in Django through Django Rest Framework is a powerful way to secure your application and simplify user authentication. By using Firebase’s authentication service, we can benefit from advanced security features and user management tools.

In addition, we can retain full control over our Django application. This blog post covers the prerequisites for Firebase Admin and Django. It also covers the step-by-step process of implementing Firebase email/password authentication in Django through the Django Rest Framework. By following these steps, we can create a robust and secure authentication system for our Django application. This will allow us to focus on building our core features.

Keep Reading

Keep Reading

Mindbowser is excited to meet healthcare industry leaders and experts from across the globe. Join us from Feb 25th to 28th, 2024, at ViVE 2024 Los Angeles.

Learn More

Let's create something together!