diff --git a/core/api/bill.py b/core/api/bill.py
index 661a1dd9a1cd8df60185e83719741c217a4afd07..01fc0ac277c80791381135dfc6a5a82670148169 100644
--- a/core/api/bill.py
+++ b/core/api/bill.py
@@ -8,11 +8,11 @@ from rest_framework import permissions, authentication
 class BillListCreate(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
     queryset = Bill.objects.all()
     serializer_class = BillSerializer
-    authentication_classes = [
-        authentication.SessionAuthentication,
-        authentication.TokenAuthentication
-    ]
-    permission_classes = (permissions.IsAuthenticated,)
+    # authentication_classes = [
+    #     authentication.SessionAuthentication,
+    #     authentication.TokenAuthentication
+    # ]
+    # permission_classes = (permissions.IsAuthenticated,)
 
     def get(self, request, *args, **kwargs):
         return self.list(request, *args, **kwargs)
@@ -50,11 +50,11 @@ class BillDetail(mixins.RetrieveModelMixin,
                  generics.GenericAPIView):
     queryset = Bill.objects.all()
     serializer_class = BillSerializer
-    authentication_classes = [
-        authentication.SessionAuthentication,
-        authentication.TokenAuthentication
-    ]
-    permission_classes = (permissions.IsAuthenticated,)
+    # authentication_classes = [
+    #     authentication.SessionAuthentication,
+    #     authentication.TokenAuthentication
+    # ]
+    # permission_classes = (permissions.IsAuthenticated,)
     lookup_field = "pk"
 
     def get(self, request, *args, **kwargs):
diff --git a/core/tests.py b/core/tests.py
deleted file mode 100644
index 10cbc14cc3ad6d17b3f45744b488bf50888cf87f..0000000000000000000000000000000000000000
--- a/core/tests.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from django.contrib.auth.models import User
-from rest_framework.test import APIClient
-from rest_framework.test import APITestCase
-from rest_framework import status
-
-from .models.profile import Profile
-
-
-class ProfileTestCase(APITestCase):
-
-    """
-    Test suite for Contact
-    """
-    def setUp(self):
-        self.client = APIClient()
-        self.data = {
-            "username": "xjhmlcy",
-            "email": "xjhmlcy@gmail.com",
-            "password": "abcdefg123"
-        }
-        self.url = "/api/auth/register"
-
-    def test_create_contact(self):
-        '''
-        test ContactViewSet create method
-        '''
-        data = self.data
-        response = self.client.post(self.url, data)
-        self.assertEqual(response.status_code, status.HTTP_200_OK)
-        self.assertEqual(User.objects.count(), 1)
-        self.assertEqual(Profile.objects.count(), 1)
-        self.assertEqual(User.objects.get().username, "xjhmlcy")
-        self.assertEqual(Profile.objects.get().user.email, "xjhmlcy@gmail.com")
diff --git a/core/tests/__init__.py b/core/tests/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/core/tests/test_auth.py b/core/tests/test_auth.py
new file mode 100644
index 0000000000000000000000000000000000000000..2920c63617b9e0ba2859e66d545cc18ced2ff3de
--- /dev/null
+++ b/core/tests/test_auth.py
@@ -0,0 +1,169 @@
+from django.contrib.auth.models import User
+from rest_framework.test import APITestCase
+from rest_framework import status
+from knox.models import AuthToken
+
+from core.models.profile import Profile
+
+
+class AuthTests(APITestCase):
+
+    """
+    Test suite for Auth
+    """
+    def add_test_person(self, username, email, password):
+        user = User.objects.create_user(username=username, email=email, password=password)
+        return AuthToken.objects.create(user)
+
+    def test_register_default(self):
+        url = "/api/auth/register"
+        data = {
+            "username": "xjhmlcy",
+            "email": "xjhmlcy@gmail.com",
+            "password": "abcdefg123"
+        }
+        response = self.client.post(url, data, format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(User.objects.count(), 1)
+        self.assertEqual(Profile.objects.count(), 1)
+        self.assertEqual(User.objects.get().username, data["username"])
+        self.assertEqual(Profile.objects.get().user.email, data["email"])
+        self.assertFalse(User.objects.get().is_active)
+    
+    def test_register_exist_email(self):
+        url = "/api/auth/register"
+        data1 = {
+            "username": "xjhmlcy",
+            "email": "xjhmlcy@gmail.com",
+            "password": "abcdefg123"
+        }
+        data2 = {
+            "username": "xjhmlcy_1",
+            "email": "xjhmlcy@gmail.com",
+            "password": "abcdefg123"
+        }
+        response = self.client.post(url, data1, format='json')
+        response = self.client.post(url, data2, format='json')
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(User.objects.count(), 1)
+        self.assertEqual(Profile.objects.count(), 1)
+        self.assertEqual(User.objects.get().username, data1["username"])
+        self.assertEqual(Profile.objects.get().user.email, data1["email"])
+    
+    def test_register_exist_username(self):
+        url = "/api/auth/register"
+        data1 = {
+            "username": "xjhmlcy",
+            "email": "xjhmlcy@gmail.com",
+            "password": "abcdefg123"
+        }
+        data2 = {
+            "username": "xjhmlcy",
+            "email": "xjhmlcy123@gmail.com",
+            "password": "abcdefg123"
+        }
+        response = self.client.post(url, data1, format='json')
+        response = self.client.post(url, data2, format='json')
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(User.objects.count(), 1)
+        self.assertEqual(Profile.objects.count(), 1)
+        self.assertEqual(User.objects.get().username, data1["username"])
+        self.assertEqual(Profile.objects.get().user.email, data1["email"])
+    
+    def test_login_default_by_username(self):
+        username = "xjhmlcy"
+        email = "xjhmlcy123@gmail.com"
+        password = "abcdefg123"
+        token, token_key = self.add_test_person(username, email, password)
+
+        url = "/api/auth/login"
+        data = {
+            "username": username,
+            "password": password
+        }
+        response = self.client.post(url, data, format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertIsNotNone(response.data.get('user', None))
+        self.assertEqual(response.data['user'].get('id', None), token.user.id)
+        self.assertEqual(response.data['user'].get('username', None), token.user.username)
+        self.assertEqual(response.data['user'].get('email', None), token.user.email)
+    
+    def test_login_default_by_email(self):
+        username = "xjhmlcy"
+        email = "xjhmlcy123@gmail.com"
+        password = "abcdefg123"
+        token, token_key = self.add_test_person(username, email, password)
+
+        url = "/api/auth/login"
+        data = {
+            "username": email,
+            "password": password
+        }
+        response = self.client.post(url, data, format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertIsNotNone(response.data.get('user', None))
+        self.assertEqual(response.data['user'].get('id', None), token.user.id)
+        self.assertEqual(response.data['user'].get('username', None), token.user.username)
+        self.assertEqual(response.data['user'].get('email', None), token.user.email)
+    
+    def test_login_wrong_password(self):
+        username = "xjhmlcy"
+        email = "xjhmlcy123@gmail.com"
+        password = "abcdefg123"
+        token, token_key = self.add_test_person(username, email, password)
+
+        url = "/api/auth/login"
+        data = {
+            "username": email,
+            "password": password + "456"
+        }
+        response = self.client.post(url, data, format='json')
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+    
+    def test_login_no_username(self):
+        url = "/api/auth/login"
+        data = {
+            "username": '123456',
+            "password": "12345678"
+        }
+        response = self.client.post(url, data, format='json')
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+    
+    def test_validate_token_default(self):
+        username = "xjhmlcy"
+        email = "xjhmlcy123@gmail.com"
+        password = "abcdefg123"
+        token, token_key = self.add_test_person(username, email, password)
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + token_key)
+
+        url = "/api/auth/validate-token"
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(response.data['valid'], 'true')
+    
+    def test_validate_token_invalid(self):
+        username = "xjhmlcy"
+        email = "xjhmlcy123@gmail.com"
+        password = "abcdefg123"
+        token, token_key = self.add_test_person(username, email, password)
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + token_key[:-1] + "1")
+        token.user.is_active = True
+        token.user.save()
+
+        url = "/api/auth/validate-token"
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(response.data['valid'], 'false')
+
+    def test_varify_user_and_activate_default(self):
+        username = "xjhmlcy"
+        email = "xjhmlcy123@gmail.com"
+        password = "abcdefg123"
+        token, token_key = self.add_test_person(username, email, password)
+        token.user.is_active = False
+        token.user.save()
+
+        url = f"/api/auth/activate/{token.digest}"
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertTrue(User.objects.get().is_active)
\ No newline at end of file
diff --git a/core/tests/test_bill.py b/core/tests/test_bill.py
new file mode 100644
index 0000000000000000000000000000000000000000..1a1946d1f8d3e450ee0d1dfee526f77135842336
--- /dev/null
+++ b/core/tests/test_bill.py
@@ -0,0 +1,96 @@
+from django.contrib.auth.models import User
+from rest_framework.test import APITestCase
+from knox.models import AuthToken
+
+from core.models.bill import Bill
+
+endpoint = "/api/bill/"
+
+data_1 = {
+    "title": "water",
+    "price": "0.85",
+    "comment": "discount",
+    "categories": 8
+}
+
+data_2 = {
+    "title": "mattress",
+    "price": "99.65",
+    "comment": "None",
+    "categories": 2
+}
+
+
+class BillTests(APITestCase):
+    def setUp(self):
+        username = "xjhmlcy"
+        email = "xjhmlcy123@gmail.com"
+        password = "abcdefg123"
+        user = User.objects.create_user(username=username, email=email, password=password)
+        token, token_key = AuthToken.objects.create(user)
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + token_key)
+
+    def test_create(self):
+        get_response_create_1 = self.client.post(endpoint, data_1, format='json')
+        get_response_create_2 = self.client.post(endpoint, data_2, format='json')
+
+        self.assertEqual(get_response_create_1.status_code, 201)
+        self.assertEqual(get_response_create_2.status_code, 201)
+        # print(get_response_create_1.data)
+
+    def test_get(self):
+        endpoint = "/api/bill/"
+        self.client.post(endpoint, data_1, format='json')
+        self.client.post(endpoint, data_2, format='json')
+
+        get_response_list_1 = self.client.get(endpoint)
+        self.assertEqual(get_response_list_1.status_code, 200)
+        # print(get_response_list_1.json())
+
+    def test_detailed_get(self):
+        endpoint = "/api/bill/"
+        self.client.post(endpoint, data_1, format='json')
+        self.client.post(endpoint, data_2, format='json')
+
+        endpoint = f"/api/bill/{Bill.objects.all()[0].id}/"
+        get_response = self.client.get(endpoint)
+        # print(get_response.json())
+        self.assertEqual(get_response.status_code, 200)
+        self.assertEqual(get_response.json()["title"],data_1["title"])
+        self.assertEqual(get_response.json()["price"],data_1["price"])
+        self.assertEqual(get_response.json()["categories"],data_1["categories"])
+        self.assertEqual(get_response.json()["comment"],data_1["comment"])
+
+    def test_detailed_update(self):
+        endpoint = "/api/bill/"
+        self.client.post(endpoint, data_1, format='json')
+        self.client.post(endpoint, data_2, format='json')
+
+        endpoint = f"/api/bill/{Bill.objects.all()[0].id}/"
+        data_updated = {
+            "title": "buttersquash",
+            "price": "0.01",
+            "comment": "juicy",
+            "categories": 4
+        }
+        get_response = self.client.put(endpoint, data_updated, format='json')
+        # print(get_response.json())
+        self.assertEqual(get_response.status_code, 200)
+        self.assertEqual(get_response.json()["title"],data_updated["title"])
+        self.assertEqual(get_response.json()["price"],data_updated["price"])
+        self.assertEqual(get_response.json()["categories"],data_updated["categories"])
+        self.assertEqual(get_response.json()["comment"],data_updated["comment"])
+
+        ## partial update
+        data_updated_2 = {
+            "title": "buttersquash",
+            "price": "56.60",
+            "comment": "juicy",
+            "categories": 4
+        }
+        get_response = self.client.put(endpoint, data_updated_2, format='json')
+        self.assertEqual(get_response.status_code, 200)
+        self.assertEqual(get_response.json()["title"],data_updated_2["title"])
+        self.assertEqual(get_response.json()["price"],data_updated_2["price"])
+        self.assertEqual(get_response.json()["categories"],data_updated_2["categories"])
+        self.assertEqual(get_response.json()["comment"],data_updated_2["comment"])
diff --git a/core/tests/test_coupon.py b/core/tests/test_coupon.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee9ae5688de3794917e97e2bbf5555115b375159
--- /dev/null
+++ b/core/tests/test_coupon.py
@@ -0,0 +1,38 @@
+from django.contrib.auth.models import User
+from rest_framework.test import APITestCase
+from rest_framework import status
+from knox.models import AuthToken
+
+from core.models.coupon import Coupon, CouponCategory
+
+
+class CouponTests(APITestCase):
+
+    """
+    Test suite for Coupon
+    """
+    def add_test_person(self, username, email, password):
+        user = User.objects.create_user(username=username, email=email, password=password)
+        return AuthToken.objects.create(user)
+
+    def add_test_coupon(self):
+        coupon_category = CouponCategory.objects.create(category='sports', sub_category='sneakers')
+        coupon = Coupon.objects.create(store='Apple', start_date='2022-12-31', expire_date='2023-12-31')
+        coupon.categories.add(coupon_category)
+        coupon.save()
+
+    def test_register_default(self):
+        username = "xjhmlcy"
+        email = "xjhmlcy123@gmail.com"
+        password = "abcdefg123"
+        token, token_key = self.add_test_person(username, email, password)
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + token_key)
+
+        self.add_test_coupon()
+
+        url = "/api/coupon"
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(Coupon.objects.count(), 1)
+        self.assertEqual(CouponCategory.objects.count(), 1)
+        self.assertEqual(response.data[0].get('store', None), 'Apple')
diff --git a/core/tests/test_password.py b/core/tests/test_password.py
new file mode 100644
index 0000000000000000000000000000000000000000..64683d05a2ba0a27f30c6c704b45ec28c18cbb1b
--- /dev/null
+++ b/core/tests/test_password.py
@@ -0,0 +1,57 @@
+from django.contrib.auth.models import User
+from rest_framework.test import APITestCase
+from rest_framework import status
+from knox.models import AuthToken
+
+from core.models.profile import Profile
+
+
+class PasswordTests(APITestCase):
+
+    """
+    Test suite for Password
+    """
+    def add_test_person(self, username, email, password):
+        user = User.objects.create_user(username=username, email=email, password=password)
+        return AuthToken.objects.create(user)
+
+    def test_password_change_default(self):
+        username = "xjhmlcy"
+        email = "xjhmlcy123@gmail.com"
+        old_password = "abcdefg123"
+        new_password = "abcdefg123456"
+        token, token_key = self.add_test_person(username, email, old_password)
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + token_key)
+
+        url = "/api/change-password"
+        data = {
+            "old_password": old_password,
+            "new_password": new_password
+        }
+        response = self.client.patch(url, data, format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+        url = "/api/auth/login"
+        data = {
+            "username": email,
+            "password": new_password
+        }
+        response = self.client.post(url, data, format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+    
+    def test_password_change_wrong_old_password(self):
+        username = "xjhmlcy"
+        email = "xjhmlcy123@gmail.com"
+        old_password = "abcdefg123"
+        new_password = "abcdefg123456"
+        token, token_key = self.add_test_person(username, email, old_password)
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + token_key)
+
+        url = "/api/change-password"
+        data = {
+            "old_password": old_password + "123",
+            "new_password": new_password
+        }
+        response = self.client.patch(url, data, format='json')
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+
diff --git a/core/tests/test_profile.py b/core/tests/test_profile.py
new file mode 100644
index 0000000000000000000000000000000000000000..72778d5d61be07e28ff06972ab607469c0eaa54e
--- /dev/null
+++ b/core/tests/test_profile.py
@@ -0,0 +1,91 @@
+from django.contrib.auth.models import User
+from rest_framework.test import APITestCase
+from rest_framework import status
+from knox.models import AuthToken
+
+from core.models.profile import Profile
+
+
+class ProfileTests(APITestCase):
+
+    """
+    Test suite for Profile
+    """
+    def add_test_person(self):
+        user = User(username='xjhmlcy', email='xjhmlcy@gmail.com', password='abcdefg123')
+        user.save()
+        return AuthToken.objects.create(user)
+
+    def test_retrive_profile(self):
+        token, token_key = self.add_test_person()
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + token_key)
+
+        url = "http://localhost:8000/api/profile"
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertIsNotNone(response.data.get('user', None))
+        self.assertEqual(response.data['user'].get('username'), token.user.username)
+        self.assertEqual(response.data['user'].get('email'), token.user.email)
+        self.assertEqual(response.data.get('bio'), '')
+        self.assertEqual(response.data.get('birthday'), None)
+        self.assertEqual(response.data.get('country'), '')
+        self.assertEqual(response.data.get('city'), '')
+        self.assertEqual(response.data.get('affiliation'), '')
+        self.assertEqual(response.data.get('photo'), 'http://testserver/media/https%3A/static.productionready.io/images/smiley-cyrus.jpg')
+    
+    def test_update_profile(self):
+        token, token_key = self.add_test_person()
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + token_key)
+
+        url = "http://localhost:8000/api/profile"
+        data = {
+            'bio': 'Hello, world!',
+            'birthday': '2000-03-09',
+            'country': 'CA',
+            'city': 'Waterloo',
+            'affiliation': 'University of Waterloo'
+        }
+        response = self.client.patch(url, data)
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertIsNotNone(response.data.get('user', None))
+        self.assertEqual(response.data['user'].get('username'), token.user.username)
+        self.assertEqual(response.data['user'].get('email'), token.user.email)
+        self.assertEqual(response.data.get('bio'), data['bio'])
+        self.assertEqual(response.data.get('birthday'), str(data['birthday']))
+        self.assertEqual(response.data.get('country'), data['country'])
+        self.assertEqual(response.data.get('city'), data['city'])
+        self.assertEqual(response.data.get('affiliation'), data['affiliation'])
+        self.assertEqual(response.data.get('photo'), 'http://testserver/media/https%3A/static.productionready.io/images/smiley-cyrus.jpg')
+
+    def test_update_username(self):
+        token, token_key = self.add_test_person()
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + token_key)
+
+        url = "http://localhost:8000/api/profile"
+        data = {
+            'user': {
+                'username': 'apple'
+            }
+        }
+        response = self.client.patch(url, data, format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertIsNotNone(User.objects.get(username=data['user']['username']))
+        self.assertIsNotNone(response.data.get('user', None))
+        self.assertEqual(response.data['user'].get('username', None), data['user']['username'])
+
+    def test_update_email(self):
+        token, token_key = self.add_test_person()
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + token_key)
+
+        url = "http://localhost:8000/api/profile"
+        data = {
+            'user': {
+                'email': 'apple@gmail.com'
+            }
+        }
+        response = self.client.patch(url, data, format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertIsNotNone(User.objects.get(email=data['user']['email']))
+        self.assertFalse(User.objects.get(email=data['user']['email']).is_active)
+        self.assertIsNotNone(response.data.get('user', None))
+        self.assertEqual(response.data['user'].get('email', None), data['user']['email'])
diff --git a/core/urls.py b/core/urls.py
index 41f46c989351b4d42102bba33429f64550b74ef0..e5180f0469c9b904cffdb0db4d4827e13c353b87 100644
--- a/core/urls.py
+++ b/core/urls.py
@@ -38,3 +38,9 @@ urlpatterns += [
     # bill search
     path('api/bill/search/', SearchBillListView.as_view(), name="bill-search")
 ]
+
+
+from rest_framework.authtoken.views import obtain_auth_token
+urlpatterns += [
+    path('api/auth/', obtain_auth_token)
+]
diff --git a/docs/requirements.md b/docs/requirements.md
new file mode 100644
index 0000000000000000000000000000000000000000..16c72f6795a23e6830f602a8bc30210913d0949a
--- /dev/null
+++ b/docs/requirements.md
@@ -0,0 +1,110 @@
+# Requiements
+
+## 1. Introduction
+
+The Budget Saver app is a mobile application designed to help users track their expenses and save money. The app includes features such as bill recording, login/register, profile management, expense tracking by category, statistics and trend charts, and a display of discount and coupons. The purpose of this document is to define the requirements for the Budget Saver app.
+
+## 2. Functional Requirements
+
+### 2.1 Bill Recording
+
+The app should allow users to record bills and expenses by entering the following information:
+
+- Bill name
+- Bill category
+- Bill amount
+- Bank Account
+- Due date
+
+The app should also provide the option to set reminders for upcoming bills.
+
+### 2.2 Login/Register
+
+The app should allow users to create an account or log in with existing accounts. The login/register feature should support the following authentication methods:
+
+- Email, username and password
+- Social accounts (e.g. Google, Apple, Facebook)
+
+### 2.3 Profile Management
+
+The app should allow users to view and update their profiles. The profile should include the following information:
+
+- Name
+- Username
+- Email address
+- Password (can be changed)
+- Bio
+- Country
+- City
+- Birthday
+- Affiliation
+- Profile picture
+
+### 2.4 Expense Tracking by Category
+
+The app should allow users to categorize their expenses and view a list of expenses by category. The categories should include, but not limited to:
+
+- Food
+- Groceries
+- Transportation
+- clothing
+- Entertainment
+- Bill
+- Sports
+- Electronics
+- Travel
+- House & Car
+- Others
+
+The app should also allow users to add new categories and edit existing ones.
+
+### 2.5 Statistics and Trend Charts
+
+The app should provide users with statistics and trend charts to help them analyze their spending habits. The statistics and charts should include, but not limited to:
+
+- Total expenses and income
+- Expenses and income by category
+- Monthly expenses and income trend
+
+### 2.6 Display of Discounts and Coupons
+
+The app should display discounts and coupons from various sources such as local stores and online retailers. The app should allow users to filter and search for discounts and coupons based on category and location.
+
+## 3. Non-Functional Requirements
+
+### 3.1 Performance
+
+The app should be able to handle a large amount of data without performance issues. The app should also load quickly and respond to user actions in a timely manner.
+
+### 3.2 Security
+
+The app should ensure the security of user data and use encryption to protect user data in transit and at rest followed by items below:
+
+- HTTPS should be implemented to ensure secure communication between the user's device and the server. This will help prevent man-in-the-middle attacks and eavesdropping.
+
+- Tokens should be used for user authentication, which helps prevent attacks such as session hijacking and cross-site request forgery (CSRF).
+
+- Passwords should be hashed using a strong hashing algorithm before storing them in the database. This ensures that even if the database is compromised, passwords cannot be easily retrieved.
+
+- The app should use a salt when hashing passwords to further enhance security.
+
+- Passwords should be checked against commonly used passwords and known compromised passwords to ensure that users are not using weak passwords.
+
+The app should also follow industry-standard security practices to prevent unauthorized access to user accounts.
+
+### 3.3 User Experience
+
+The app should provide a user-friendly and intuitive interface. The app should also be accessible to users with disabilities.
+
+### 3.4 Platform Compatibility
+
+The app should be compatible with the latest versions of popular mobile platforms such as Android and iOS.
+
+## 4. Constraints
+
+The development of the Budget Saver app should adhere to the following constraints:
+
+- The app should be developed using modern software engineering practices and follow coding standards.
+- The app should be developed using scalable and maintainable architecture.
+- The app should be developed within a reasonable budget and timeframe.
+- The app should be tested thoroughly to ensure quality and reliability.
diff --git a/ece651_backend/settings.py b/ece651_backend/settings.py
index 6a0882d1caf9cc48639fce43ca0a7b177b4a1035..1c33262fa1aa0374c02cd8852f4b26b0306aae17 100644
--- a/ece651_backend/settings.py
+++ b/ece651_backend/settings.py
@@ -40,6 +40,7 @@ INSTALLED_APPS = [
     'django.contrib.staticfiles',
     'django_extensions',
     'rest_framework',
+    'rest_framework.authtoken',
     'django_rest_passwordreset',
     'knox',
     'core',
diff --git a/requirements.txt b/requirements.txt
index 6a627f77af0d50750a2c6fab937a49a11735f063..d88b30b8e47c8fa32d85748a9626a302f05ce041 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
+coverage==6.3.2
 Django==4.1
 django_countries==7.5
 django_extensions==3.2.1