diff --git a/src/backend/InvenTree/InvenTree/forms.py b/src/backend/InvenTree/InvenTree/forms.py
index d2d2278f64..4d6de19d59 100644
--- a/src/backend/InvenTree/InvenTree/forms.py
+++ b/src/backend/InvenTree/InvenTree/forms.py
@@ -15,8 +15,6 @@ from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
 from crispy_forms.bootstrap import AppendedText, PrependedAppendedText, PrependedText
 from crispy_forms.helper import FormHelper
 from crispy_forms.layout import Field, Layout
-from dj_rest_auth.registration.serializers import RegisterSerializer
-from rest_framework import serializers
 
 import InvenTree.helpers_model
 import InvenTree.sso
@@ -341,21 +339,3 @@ class CustomSocialAccountAdapter(
         # Log the error to the database
         log_error(path, error_name=error, error_data=exception)
         logger.error("SSO error for provider '%s' - check admin error log", provider_id)
-
-
-# override dj-rest-auth
-class CustomRegisterSerializer(RegisterSerializer):
-    """Override of serializer to use dynamic settings."""
-
-    email = serializers.EmailField()
-
-    def __init__(self, instance=None, data=..., **kwargs):
-        """Check settings to influence which fields are needed."""
-        kwargs['email_required'] = get_global_setting('LOGIN_MAIL_REQUIRED')
-        super().__init__(instance, data, **kwargs)
-
-    def save(self, request):
-        """Override to check if registration is open."""
-        if registration_enabled():
-            return super().save(request)
-        raise forms.ValidationError(_('Registration is disabled.'))
diff --git a/src/backend/InvenTree/InvenTree/settings.py b/src/backend/InvenTree/InvenTree/settings.py
index cf10fa394d..6fe0448e31 100644
--- a/src/backend/InvenTree/InvenTree/settings.py
+++ b/src/backend/InvenTree/InvenTree/settings.py
@@ -235,8 +235,6 @@ INSTALLED_APPS = [
     'django_otp',  # OTP is needed for MFA - base package
     'django_otp.plugins.otp_totp',  # Time based OTP
     'django_otp.plugins.otp_static',  # Backup codes
-    'dj_rest_auth',  # Authentication APIs - dj-rest-auth
-    'dj_rest_auth.registration',  # Registration APIs - dj-rest-auth'
     'drf_spectacular',  # API documentation
     'django_ical',  # For exporting calendars
 ]
@@ -484,33 +482,6 @@ if DEBUG:
         'rest_framework.renderers.BrowsableAPIRenderer'
     )
 
-# JWT switch
-USE_JWT = get_boolean_setting('INVENTREE_USE_JWT', 'use_jwt', False)
-REST_USE_JWT = USE_JWT
-
-# dj-rest-auth
-REST_AUTH = {
-    'SESSION_LOGIN': True,
-    'TOKEN_MODEL': 'users.models.ApiToken',
-    'TOKEN_CREATOR': 'users.models.default_create_token',
-    'USE_JWT': USE_JWT,
-}
-
-OLD_PASSWORD_FIELD_ENABLED = True
-REST_AUTH_REGISTER_SERIALIZERS = {
-    'REGISTER_SERIALIZER': 'InvenTree.forms.CustomRegisterSerializer'
-}
-
-# JWT settings - rest_framework_simplejwt
-if USE_JWT:
-    JWT_AUTH_COOKIE = 'inventree-auth'
-    JWT_AUTH_REFRESH_COOKIE = 'inventree-token'
-    REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'].append(
-        'dj_rest_auth.jwt_auth.JWTCookieAuthentication'
-    )
-    INSTALLED_APPS.append('rest_framework_simplejwt')
-
-
 # WSGI default setting
 WSGI_APPLICATION = 'InvenTree.wsgi.application'
 
diff --git a/src/backend/InvenTree/InvenTree/social_auth_urls.py b/src/backend/InvenTree/InvenTree/social_auth_urls.py
deleted file mode 100644
index 49d9e461ee..0000000000
--- a/src/backend/InvenTree/InvenTree/social_auth_urls.py
+++ /dev/null
@@ -1,267 +0,0 @@
-"""API endpoints for social authentication with allauth."""
-
-import logging
-from importlib import import_module
-
-from django.urls import NoReverseMatch, include, path, reverse
-
-from allauth.account.models import EmailAddress
-from allauth.socialaccount import providers
-from allauth.socialaccount.providers.oauth2.views import OAuth2Adapter, OAuth2LoginView
-from drf_spectacular.utils import OpenApiResponse, extend_schema
-from rest_framework import serializers
-from rest_framework.exceptions import NotFound
-from rest_framework.permissions import AllowAny, IsAuthenticated
-from rest_framework.response import Response
-
-import InvenTree.sso
-from common.settings import get_global_setting
-from InvenTree.mixins import CreateAPI, ListAPI, ListCreateAPI
-from InvenTree.serializers import EmptySerializer, InvenTreeModelSerializer
-
-logger = logging.getLogger('inventree')
-
-
-class GenericOAuth2ApiLoginView(OAuth2LoginView):
-    """Api view to login a user with a social account."""
-
-    def dispatch(self, request, *args, **kwargs):
-        """Dispatch the regular login view directly."""
-        return self.login(request, *args, **kwargs)
-
-
-class GenericOAuth2ApiConnectView(GenericOAuth2ApiLoginView):
-    """Api view to connect a social account to the current user."""
-
-    def dispatch(self, request, *args, **kwargs):
-        """Dispatch the connect request directly."""
-        # Override the request method be in connection mode
-        request.GET = request.GET.copy()
-        request.GET['process'] = 'connect'
-
-        # Resume the dispatch
-        return super().dispatch(request, *args, **kwargs)
-
-
-def handle_oauth2(adapter: OAuth2Adapter):
-    """Define urls for oauth2 endpoints."""
-    return [
-        path(
-            'login/',
-            GenericOAuth2ApiLoginView.adapter_view(adapter),
-            name=f'{provider.id}_api_login',
-        ),
-        path(
-            'connect/',
-            GenericOAuth2ApiConnectView.adapter_view(adapter),
-            name=f'{provider.id}_api_connect',
-        ),
-    ]
-
-
-legacy = {
-    'twitter': 'twitter_oauth2',
-    'bitbucket': 'bitbucket_oauth2',
-    'linkedin': 'linkedin_oauth2',
-    'vimeo': 'vimeo_oauth2',
-    'openid': 'openid_connect',
-}  # legacy connectors
-
-
-# Collect urls for all loaded providers
-social_auth_urlpatterns = []
-
-provider_urlpatterns = []
-
-for name, provider in providers.registry.provider_map.items():
-    try:
-        prov_mod = import_module(provider.get_package() + '.views')
-    except ImportError:
-        logger.exception('Could not import authentication provider %s', name)
-        continue
-
-    # Try to extract the adapter class
-    adapters = [
-        cls
-        for cls in prov_mod.__dict__.values()
-        if isinstance(cls, type)
-        and cls != OAuth2Adapter
-        and issubclass(cls, OAuth2Adapter)
-    ]
-
-    # Get urls
-    urls = []
-    if len(adapters) == 1:
-        urls = handle_oauth2(adapter=adapters[0])
-    else:
-        if provider.id in legacy:
-            logger.warning(
-                '`%s` is not supported on platform UI. Use `%s` instead.',
-                provider.id,
-                legacy[provider.id],
-            )
-            continue
-        else:
-            logger.error(
-                'Found handler that is not yet ready for platform UI: `%s`. Open an feature request on GitHub if you need it implemented.',
-                provider.id,
-            )
-            continue
-    provider_urlpatterns += [path(f'{provider.id}/', include(urls))]
-
-
-social_auth_urlpatterns += provider_urlpatterns
-
-
-class SocialProviderListResponseSerializer(serializers.Serializer):
-    """Serializer for the SocialProviderListView."""
-
-    class SocialProvider(serializers.Serializer):
-        """Serializer for the SocialProviderListResponseSerializer."""
-
-        id = serializers.CharField()
-        name = serializers.CharField()
-        configured = serializers.BooleanField()
-        login = serializers.URLField()
-        connect = serializers.URLField()
-        display_name = serializers.CharField()
-
-    sso_enabled = serializers.BooleanField()
-    sso_registration = serializers.BooleanField()
-    mfa_required = serializers.BooleanField()
-    providers = SocialProvider(many=True)
-    registration_enabled = serializers.BooleanField()
-    password_forgotten_enabled = serializers.BooleanField()
-
-
-class SocialProviderListView(ListAPI):
-    """List of available social providers."""
-
-    permission_classes = (AllowAny,)
-    serializer_class = EmptySerializer
-
-    @extend_schema(
-        responses={200: OpenApiResponse(response=SocialProviderListResponseSerializer)}
-    )
-    def get(self, request, *args, **kwargs):
-        """Get the list of providers."""
-        provider_list = []
-        for provider in providers.registry.provider_map.values():
-            provider_data = {
-                'id': provider.id,
-                'name': provider.name,
-                'configured': False,
-            }
-
-            try:
-                provider_data['login'] = request.build_absolute_uri(
-                    reverse(f'{provider.id}_api_login')
-                )
-            except NoReverseMatch:
-                provider_data['login'] = None
-
-            try:
-                provider_data['connect'] = request.build_absolute_uri(
-                    reverse(f'{provider.id}_api_connect')
-                )
-            except NoReverseMatch:
-                provider_data['connect'] = None
-
-            provider_data['configured'] = InvenTree.sso.check_provider(provider)
-            provider_data['display_name'] = InvenTree.sso.provider_display_name(
-                provider
-            )
-
-            provider_list.append(provider_data)
-
-        data = {
-            'sso_enabled': InvenTree.sso.login_enabled(),
-            'sso_registration': InvenTree.sso.registration_enabled(),
-            'mfa_required': get_global_setting('LOGIN_ENFORCE_MFA'),
-            'providers': provider_list,
-            'registration_enabled': get_global_setting('LOGIN_ENABLE_REG'),
-            'password_forgotten_enabled': get_global_setting('LOGIN_ENABLE_PWD_FORGOT'),
-        }
-        return Response(data)
-
-
-class EmailAddressSerializer(InvenTreeModelSerializer):
-    """Serializer for the EmailAddress model."""
-
-    class Meta:
-        """Meta options for EmailAddressSerializer."""
-
-        model = EmailAddress
-        fields = '__all__'
-
-
-class EmptyEmailAddressSerializer(InvenTreeModelSerializer):
-    """Empty Serializer for the EmailAddress model."""
-
-    class Meta:
-        """Meta options for EmailAddressSerializer."""
-
-        model = EmailAddress
-        fields = []
-
-
-class EmailListView(ListCreateAPI):
-    """List of registered email addresses for current users."""
-
-    permission_classes = (IsAuthenticated,)
-    serializer_class = EmailAddressSerializer
-
-    def get_queryset(self):
-        """Only return data for current user."""
-        return EmailAddress.objects.filter(user=self.request.user)
-
-
-class EmailActionMixin(CreateAPI):
-    """Mixin to modify email addresses for current users."""
-
-    serializer_class = EmptyEmailAddressSerializer
-    permission_classes = (IsAuthenticated,)
-
-    def get_queryset(self):
-        """Filter queryset for current user."""
-        return EmailAddress.objects.filter(
-            user=self.request.user, pk=self.kwargs['pk']
-        ).first()
-
-    @extend_schema(responses={200: OpenApiResponse(response=EmailAddressSerializer)})
-    def post(self, request, *args, **kwargs):
-        """Filter item, run action and return data."""
-        email = self.get_queryset()
-        if not email:
-            raise NotFound
-
-        self.special_action(email, request, *args, **kwargs)
-        return Response(EmailAddressSerializer(email).data)
-
-
-class EmailVerifyView(EmailActionMixin):
-    """Re-verify an email for a currently logged in user."""
-
-    def special_action(self, email, request, *args, **kwargs):
-        """Send confirmation."""
-        if email.verified:
-            return
-        email.send_confirmation(request)
-
-
-class EmailPrimaryView(EmailActionMixin):
-    """Make an email for a currently logged in user primary."""
-
-    def special_action(self, email, *args, **kwargs):
-        """Mark email as primary."""
-        if email.primary:
-            return
-        email.set_as_primary()
-
-
-class EmailRemoveView(EmailActionMixin):
-    """Remove an email for a currently logged in user."""
-
-    def special_action(self, email, *args, **kwargs):
-        """Delete email."""
-        email.delete()
diff --git a/src/backend/InvenTree/InvenTree/sso.py b/src/backend/InvenTree/InvenTree/sso.py
index b3fb551cf2..86d5c3346d 100644
--- a/src/backend/InvenTree/InvenTree/sso.py
+++ b/src/backend/InvenTree/InvenTree/sso.py
@@ -53,15 +53,6 @@ def check_provider(provider):
     return True
 
 
-def provider_display_name(provider):
-    """Return the 'display name' for the given provider."""
-    if app := get_provider_app(provider):
-        return app.name
-
-    # Fallback value if app not found
-    return provider.name
-
-
 def login_enabled() -> bool:
     """Return True if SSO login is enabled."""
     return str2bool(get_global_setting('LOGIN_ENABLE_SSO'))
diff --git a/src/backend/InvenTree/InvenTree/urls.py b/src/backend/InvenTree/InvenTree/urls.py
index a9fa1cd0e0..a0a3ce58c3 100644
--- a/src/backend/InvenTree/InvenTree/urls.py
+++ b/src/backend/InvenTree/InvenTree/urls.py
@@ -10,11 +10,6 @@ from django.urls import include, path, re_path
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic.base import RedirectView
 
-from dj_rest_auth.registration.views import (
-    ConfirmEmailView,
-    SocialAccountDisconnectView,
-    SocialAccountListView,
-)
 from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView
 from sesame.views import LoginView
 
@@ -47,14 +42,6 @@ from .api import (
     VersionView,
 )
 from .magic_login import GetSimpleLoginView
-from .social_auth_urls import (
-    EmailListView,
-    EmailPrimaryView,
-    EmailRemoveView,
-    EmailVerifyView,
-    SocialProviderListView,
-    social_auth_urlpatterns,
-)
 from .views import (
     AboutView,
     AppearanceSelectView,
@@ -130,58 +117,12 @@ apipatterns = [
     path(
         'auth/',
         include([
-            re_path(
-                r'^registration/account-confirm-email/(?P<key>[-:\w]+)/$',
-                ConfirmEmailView.as_view(),
-                name='account_confirm_email',
-            ),
-            path('registration/', include('dj_rest_auth.registration.urls')),
-            path(
-                'providers/', SocialProviderListView.as_view(), name='social_providers'
-            ),
-            path(
-                'emails/',
-                include([
-                    path(
-                        '<int:pk>/',
-                        include([
-                            path(
-                                'primary/',
-                                EmailPrimaryView.as_view(),
-                                name='email-primary',
-                            ),
-                            path(
-                                'verify/',
-                                EmailVerifyView.as_view(),
-                                name='email-verify',
-                            ),
-                            path(
-                                'remove/',
-                                EmailRemoveView().as_view(),
-                                name='email-remove',
-                            ),
-                        ]),
-                    ),
-                    path('', EmailListView.as_view(), name='email-list'),
-                ]),
-            ),
-            path('social/', include(social_auth_urlpatterns)),
-            path(
-                'social/', SocialAccountListView.as_view(), name='social_account_list'
-            ),
-            path(
-                'social/<int:pk>/disconnect/',
-                SocialAccountDisconnectView.as_view(),
-                name='social_account_disconnect',
-            ),
-            path('login/', users.api.Login.as_view(), name='api-login'),
             path('logout/', users.api.Logout.as_view(), name='api-logout'),
             path(
                 'login-redirect/',
                 users.api.LoginRedirect.as_view(),
                 name='api-login-redirect',
             ),
-            path('', include('dj_rest_auth.urls')),
         ]),
     ),
     # Magic login URLs
@@ -410,7 +351,6 @@ classic_frontendpatterns = [
     path('stock/', include(stock_urls)),
     path('supplier-part/', include(supplier_part_urls)),
     path('edit-user/', EditUserView.as_view(), name='edit-user'),
-    path('set-password/', SetPasswordView.as_view(), name='set-password'),
     path('index/', IndexView.as_view(), name='index'),
     path('notifications/', include(notifications_urls)),
     path('search/', SearchView.as_view(), name='search'),
diff --git a/src/backend/InvenTree/InvenTree/views.py b/src/backend/InvenTree/InvenTree/views.py
index 176e704b19..931520a40f 100644
--- a/src/backend/InvenTree/InvenTree/views.py
+++ b/src/backend/InvenTree/InvenTree/views.py
@@ -405,58 +405,6 @@ class EditUserView(AjaxUpdateView):
         return self.request.user
 
 
-class SetPasswordView(AjaxUpdateView):
-    """View for setting user password."""
-
-    ajax_template_name = 'InvenTree/password.html'
-    ajax_form_title = _('Set Password')
-    form_class = SetPasswordForm
-
-    def get_object(self):
-        """Set form to edit current user."""
-        return self.request.user
-
-    def post(self, request, *args, **kwargs):
-        """Validate inputs and change password."""
-        form = self.get_form()
-
-        valid = form.is_valid()
-
-        p1 = request.POST.get('enter_password', '')
-        p2 = request.POST.get('confirm_password', '')
-        old_password = request.POST.get('old_password', '')
-        user = self.request.user
-
-        if valid:
-            # Passwords must match
-
-            if p1 != p2:
-                error = _('Password fields must match')
-                form.add_error('enter_password', error)
-                form.add_error('confirm_password', error)
-                valid = False
-
-        if valid:
-            # Old password must be correct
-            if user.has_usable_password() and not user.check_password(old_password):
-                form.add_error('old_password', _('Wrong password provided'))
-                valid = False
-
-        if valid:
-            try:
-                # Validate password
-                password_validation.validate_password(p1, user)
-
-                # Update the user
-                user.set_password(p1)
-                user.save()
-            except ValidationError as error:
-                form.add_error('confirm_password', str(error))
-                valid = False
-
-        return self.renderJsonResponse(request, form, data={'form_valid': valid})
-
-
 class IndexView(TemplateView):
     """View for InvenTree index page."""
 
diff --git a/src/backend/InvenTree/users/api.py b/src/backend/InvenTree/users/api.py
index bbdc3be975..c0b8e11220 100644
--- a/src/backend/InvenTree/users/api.py
+++ b/src/backend/InvenTree/users/api.py
@@ -3,26 +3,17 @@
 import datetime
 import logging
 
-from django.contrib.auth import authenticate, get_user, login, logout
+from django.contrib.auth import get_user, login
 from django.contrib.auth.models import Group, User
-from django.http.response import HttpResponse
-from django.shortcuts import redirect
-from django.urls import include, path, re_path, reverse
+from django.urls import include, path, re_path
 from django.views.generic.base import RedirectView
 
-from allauth.account import app_settings
-from allauth.account.adapter import get_adapter
-from allauth_2fa.utils import user_has_valid_totp_device
-from dj_rest_auth.views import LoginView, LogoutView
 from drf_spectacular.utils import OpenApiResponse, extend_schema, extend_schema_view
 from rest_framework import exceptions, permissions
-from rest_framework.authentication import BasicAuthentication
-from rest_framework.decorators import authentication_classes
 from rest_framework.response import Response
 from rest_framework.views import APIView
 
 import InvenTree.helpers
-from common.models import InvenTreeSetting
 from InvenTree.filters import SEARCH_ORDER_FILTER
 from InvenTree.mixins import (
     ListAPI,
@@ -184,67 +175,12 @@ class GroupList(ListCreateAPI):
     ordering_fields = ['name']
 
 
-@authentication_classes([BasicAuthentication])
-@extend_schema_view(
-    post=extend_schema(
-        responses={200: OpenApiResponse(description='User successfully logged in')}
-    )
-)
-class Login(LoginView):
-    """API view for logging in via API."""
-
-    def post(self, request, *args, **kwargs):
-        """API view for logging in via API."""
-        _data = request.data.copy()
-        _data.update(request.POST.copy())
-
-        if not _data.get('mfa', None):
-            return super().post(request, *args, **kwargs)
-
-        # Check if login credentials valid
-        user = authenticate(
-            request, username=_data.get('username'), password=_data.get('password')
-        )
-        if user is None:
-            return HttpResponse(status=401)
-
-            # Check if user has mfa set up
-        if not user_has_valid_totp_device(user):
-            return super().post(request, *args, **kwargs)
-
-            # Stage login and redirect to 2fa
-        request.session['allauth_2fa_user_id'] = str(user.id)
-        request.session['allauth_2fa_login'] = {
-            'email_verification': app_settings.EMAIL_VERIFICATION,
-            'signal_kwargs': None,
-            'signup': False,
-            'email': None,
-            'redirect_url': reverse('platform'),
-        }
-        return redirect(reverse('two-factor-authenticate'))
-
-    def process_login(self):
-        """Process the login request, ensure that MFA is enforced if required."""
-        # Normal login process
-        ret = super().process_login()
-        user = self.request.user
-        adapter = get_adapter(self.request)
-
-        # User requires 2FA or MFA is enforced globally - no logins via API
-        if adapter.has_2fa_enabled(user) or InvenTreeSetting.get_setting(
-            'LOGIN_ENFORCE_MFA'
-        ):
-            logout(self.request)
-            raise exceptions.PermissionDenied('MFA required for this user')
-        return ret
-
-
 @extend_schema_view(
     post=extend_schema(
         responses={200: OpenApiResponse(description='User successfully logged out')}
     )
 )
-class Logout(LogoutView):
+class Logout(APIView):
     """API view for logging out via API."""
 
     serializer_class = None
diff --git a/src/backend/requirements.in b/src/backend/requirements.in
index 4dd4af8b4f..4de3ab4a4c 100644
--- a/src/backend/requirements.in
+++ b/src/backend/requirements.in
@@ -33,7 +33,6 @@ django-weasyprint                       # django weasyprint integration
 djangorestframework                     # DRF framework
 djangorestframework-simplejwt[crypto]   # JWT authentication
 django-xforwardedfor-middleware         # IP forwarding metadata
-dj-rest-auth                            # Authentication API endpoints
 dulwich                                 # pure Python git integration
 drf-spectacular                         # DRF API documentation
 feedparser                              # RSS newsfeed parser
diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt
index 1dca2b204d..81012cc7cb 100644
--- a/src/backend/requirements.txt
+++ b/src/backend/requirements.txt
@@ -327,13 +327,10 @@ diff-match-patch==20230430 \
     --hash=sha256:953019cdb9c9d2c9e47b5b12bcff3cf4746fc4598eb406076fa1fc27e6a1f15c \
     --hash=sha256:dce43505fb7b1b317de7195579388df0746d90db07015ed47a85e5e44930ef93
     # via django-import-export
-dj-rest-auth==6.0.0 \
-    --hash=sha256:760b45f3a07cd6182e6a20fe07d0c55230c5f950167df724d7914d0dd8c50133
 django==4.2.12 \
     --hash=sha256:6a6b4aff8a2db2dc7dcc5650cb2c7a7a0d1eb38e2aa2335fdf001e41801e9797 \
     --hash=sha256:7640e86835d44ae118c2916a803d8081f40e214ee18a5a92a0202994ca60a4b4
     # via
-    #   dj-rest-auth
     #   django-allauth
     #   django-cors-headers
     #   django-dbbackup
@@ -455,7 +452,6 @@ djangorestframework==3.14.0 \
     --hash=sha256:579a333e6256b09489cbe0a067e66abe55c6595d8926be6b99423786334350c8 \
     --hash=sha256:eb63f58c9f218e1a7d064d17a70751f528ed4e1d35547fdade9aaf4cd103fd08
     # via
-    #   dj-rest-auth
     #   djangorestframework-simplejwt
     #   drf-spectacular
 djangorestframework-simplejwt[crypto]==5.3.1 \