DEV Community

Cover image for My Journey as a Backend Developer: Solving Complex Authentication and Authorization Challenge
kihuni
kihuni

Posted on

My Journey as a Backend Developer: Solving Complex Authentication and Authorization Challenge

Being a backend developer often means solving complex problems that require a deep understanding of the underlying systems and technologies. Recently, I faced a challenging issue related to authentication and authorization in a Django project. Here’s a detailed breakdown of how I tackled this problem and why I’m excited about the journey I’m about to start with the HNG Internship.

The Problem: Custom Authentication and Authorization

In a recent project, I was tasked with implementing a custom authentication system that required users to log in using their email addresses instead of usernames. Additionally, the project had specific authorization requirements, such as role-based access control (RBAC) to manage user permissions efficiently.

Step-by-Step Solution

  • Step 1: Custom User Model

The first step was to create a custom user model that used email as the unique identifier. This involved subclassing Django’s AbstractBaseUser and BaseUserManager.

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

class MyUserManager(BaseUserManager):
    def create_user(self, email, password=None):
        if not email:
            raise ValueError("Users must have an email address")
        user = self.model(email=self.normalize_email(email))
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None):
        user = self.create_user(email, password)
        user.is_admin = True
        user.save(using=self._db)
        return user

class MyUser(AbstractBaseUser):
    email = models.EmailField(unique=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'

Enter fullscreen mode Exit fullscreen mode
  • Step 2: Update Settings

Next, I updated the settings to use the custom user model.

AUTH_USER_MODEL = 'myapp.MyUser'
Enter fullscreen mode Exit fullscreen mode
  • Step 3: Custom Authentication Backend

To support authentication via email, I created a custom authentication backend.

from django.contrib.auth.backends import BaseBackend
from django.contrib.auth import get_user_model

class EmailBackend(BaseBackend):
    def authenticate(self, request, email=None, password=None):
        User = get_user_model()
        try:
            user = User.objects.get(email=email)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        User = get_user_model()
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

Enter fullscreen mode Exit fullscreen mode
  • Step 4: Update Authentication Backends

I updated the AUTHENTICATION_BACKENDS setting to include the custom backend.

AUTHENTICATION_BACKENDS = [
    'myapp.backends.EmailBackend',
    'django.contrib.auth.backends.ModelBackend',
]

Enter fullscreen mode Exit fullscreen mode
  • Step 5: Implement Role-Based Access Control (RBAC)

For RBAC, I used Django’s built-in groups and permissions. I defined custom permissions in the Meta class of relevant models and assigned these permissions to user groups.

class MyModel(models.Model):
    ...
    class Meta:
        permissions = [
            ("can_view", "Can view"),
            ("can_edit", "Can edit"),
        ]

Enter fullscreen mode Exit fullscreen mode

Assigning permissions to groups:

from django.contrib.auth.models import Group, Permission

view_permission = Permission.objects.get(codename='can_view')
edit_permission = Permission.objects.get(codename='can_edit')

viewer_group = Group.objects.create(name='Viewers')
viewer_group.permissions.add(view_permission)

editor_group = Group.objects.create(name='Editors')
editor_group.permissions.add(view_permission, edit_permission)

Enter fullscreen mode Exit fullscreen mode

Checking permissions in views:

from django.contrib.auth.decorators import permission_required

@permission_required('myapp.can_view')
def my_view(request):
    ...

Enter fullscreen mode Exit fullscreen mode

Personal Journey and HNG Internship

My journey as a backend developer has been marked by continuous learning and problem-solving. Each challenge, like the one described above, has honed my skills and deepened my understanding of web development.

I am about to embark on an exciting journey with the HNG Internship. This opportunity is about enhancing my technical skills and networking with like-minded professionals and mentors who can guide me toward excellence. The internship offers a platform to work on real-world projects, which is invaluable for practical learning.

Why HNG Internship?

  • Hands-on Experience: The internship will allow me to work on diverse projects, sharpening my problem-solving skills.

  • Mentorship: Access to experienced mentors will provide guidance and insights that are crucial for professional growth.

  • Networking: Connecting with peers and industry professionals will expand my professional network, opening up future opportunities.

Conclusion

Solving complex problems is a significant part of being a backend developer. The challenge of implementing custom authentication and authorization in Django not only tested my skills but also reaffirmed my passion for backend development. As I step into the HNG Internship, I am eager to learn, grow, and contribute to impactful projects. This journey is a stepping stone towards a future where I can leverage my skills to build secure and efficient applications.

Top comments (0)