Index: backend/auth_form/serializers.py
===================================================================
--- backend/auth_form/serializers.py	(revision 180656aaf7d3ad3fe937a5c25930480b77439d0b)
+++ backend/auth_form/serializers.py	(revision 367b83f4d0f1329a5f1e9c76fc25af940eb24c03)
@@ -1,5 +1,6 @@
-from django.contrib.auth import get_user_model
+from django.contrib.auth import get_user_model, authenticate
 from rest_framework import serializers
 from django.contrib.auth.password_validation import validate_password
+from rest_framework.exceptions import AuthenticationFailed
 
 User = get_user_model()
@@ -29,2 +30,23 @@
 
         return user
+
+class LoginSerializer(serializers.Serializer):
+    email = serializers.EmailField(required=True)
+    password = serializers.CharField(required=True, write_only=True)
+
+    def validate(self, data):
+        email = data.get('email')
+        password = data.get('password')
+
+        # AuthenticationFailed error
+        if email and password:
+            user = authenticate(username=email, password=password)
+            if user is None:
+                raise AuthenticationFailed('Invalid email or password')
+            if not user.is_active:
+                raise AuthenticationFailed('User account is disabled')
+            
+            data['user'] = user
+            return data
+        else:
+            serializers.ValidationError('Must include "email" and "password"')
Index: backend/auth_form/urls.py
===================================================================
--- backend/auth_form/urls.py	(revision 180656aaf7d3ad3fe937a5c25930480b77439d0b)
+++ backend/auth_form/urls.py	(revision 367b83f4d0f1329a5f1e9c76fc25af940eb24c03)
@@ -1,6 +1,6 @@
 from django.urls import path
-from .views import RegisterView
+from .views import RegisterView, LoginView
 urlpatterns = [
     path('register/', RegisterView.as_view(), name='register'),
-    # path('login/', LoginView.as_view(), name='login')
+    path('login/', LoginView.as_view(), name='login')
 ]
Index: backend/auth_form/views.py
===================================================================
--- backend/auth_form/views.py	(revision 180656aaf7d3ad3fe937a5c25930480b77439d0b)
+++ backend/auth_form/views.py	(revision 367b83f4d0f1329a5f1e9c76fc25af940eb24c03)
@@ -1,6 +1,7 @@
-from .serializers import RegistrationSerializer
+from .serializers import RegistrationSerializer, LoginSerializer
 from rest_framework import serializers, status, views
 from rest_framework.views import APIView
 from rest_framework.response import Response
+from rest_framework_simplejwt.tokens import RefreshToken
 
 # Create your views here.
@@ -24,2 +25,19 @@
         # If the serializer is not valid, return an error response
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+
+class LoginView(APIView):
+    def post(self, request):
+        serializer = LoginSerializer(data = request.data)
+        # Another way of doing error checking istead of .is_valid()
+        serializer.is_valid(raise_exception=True)
+        user = serializer.validated_data['user']
+
+        refresh = RefreshToken.for_user(user)
+        return Response({
+            'refresh': str(refresh),
+            'access': str(refresh.access_token),
+            'user_id': user.id,
+            'role': user.role,
+        }, status=status.HTTP_200_OK)
+
+
Index: backend/backend/backends.py
===================================================================
--- backend/backend/backends.py	(revision 367b83f4d0f1329a5f1e9c76fc25af940eb24c03)
+++ backend/backend/backends.py	(revision 367b83f4d0f1329a5f1e9c76fc25af940eb24c03)
@@ -0,0 +1,15 @@
+from django.contrib.auth.backends import ModelBackend
+from django.contrib.auth import get_user_model
+
+class EmailBackend(ModelBackend):
+    """
+    Custom authentication backend to authenticate using email instead of username.
+    """
+    def authenticate(self, request, username=None, password=None, **kwargs):
+        try:
+            # Try to get the user based on the provided email (username is set to email)
+            user = get_user_model().objects.get(email=username)
+            if user.check_password(password):  # Check if the password is correct
+                return user  # If valid, return the user
+        except get_user_model().DoesNotExist:
+            return None  # Return None if user doesn't exist
Index: backend/backend/settings.py
===================================================================
--- backend/backend/settings.py	(revision 180656aaf7d3ad3fe937a5c25930480b77439d0b)
+++ backend/backend/settings.py	(revision 367b83f4d0f1329a5f1e9c76fc25af940eb24c03)
@@ -55,9 +55,10 @@
 
 SIMPLE_JWT = {
-    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
-    'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
+    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
+    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
     'ROTATE_REFRESH_TOKENS': False,
     'BLACKLIST_AFTER_ROTATION': True,
     'UPDATE_LAST_LOGIN': False,
+    'AUTH_HEADER_TYPES': ('Bearer',),
 }
 
@@ -154,2 +155,7 @@
 DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
 AUTH_USER_MODEL = 'auth_form.User'
+
+AUTHENTICATION_BACKENDS = [
+    'django.contrib.auth.backends.ModelBackend',  # default backend
+    'backend.backends.EmailBackend',  # custom backend to authenticate using email
+]
