diff --git a/backend/igny8_core/auth/urls.py b/backend/igny8_core/auth/urls.py index 4ce2c2b6..2b3fb7bd 100644 --- a/backend/igny8_core/auth/urls.py +++ b/backend/igny8_core/auth/urls.py @@ -9,6 +9,7 @@ from rest_framework.response import Response from rest_framework import status, permissions from drf_spectacular.utils import extend_schema from igny8_core.api.response import success_response, error_response +from django.conf import settings from .views import ( GroupsViewSet, UsersViewSet, AccountsViewSet, SubscriptionsViewSet, SiteUserAccessViewSet, PlanViewSet, SiteViewSet, SectorViewSet, @@ -285,6 +286,44 @@ class LoginView(APIView): ) +@extend_schema( + tags=['Authentication'], + summary='User Logout', + description='Clear session and logout user' +) +class LogoutView(APIView): + """Logout endpoint.""" + permission_classes = [permissions.AllowAny] + + def post(self, request): + from django.contrib.auth import logout as django_logout + + # Clear Django auth session + django_logout(request) + try: + request.session.flush() + except Exception: + # If session is unavailable or already cleared, ignore + pass + + response = success_response( + message='Logged out successfully', + request=request + ) + + # Explicitly expire session cookie across domain/path + try: + response.delete_cookie( + settings.SESSION_COOKIE_NAME, + path=getattr(settings, 'SESSION_COOKIE_PATH', '/'), + domain=getattr(settings, 'SESSION_COOKIE_DOMAIN', None) + ) + except Exception: + # If settings are misconfigured, still return success + pass + + return response + @extend_schema( tags=['Authentication'], summary='Request Password Reset', @@ -684,6 +723,7 @@ urlpatterns = [ path('', include(router.urls)), path('register/', csrf_exempt(RegisterView.as_view()), name='auth-register'), path('login/', csrf_exempt(LoginView.as_view()), name='auth-login'), + path('logout/', csrf_exempt(LogoutView.as_view()), name='auth-logout'), path('refresh/', csrf_exempt(RefreshTokenView.as_view()), name='auth-refresh'), path('change-password/', ChangePasswordView.as_view(), name='auth-change-password'), path('password-reset/', csrf_exempt(PasswordResetRequestView.as_view()), name='auth-password-reset-request'), diff --git a/frontend/src/components/auth/SignInForm.tsx b/frontend/src/components/auth/SignInForm.tsx index 9495f125..4da1bd89 100644 --- a/frontend/src/components/auth/SignInForm.tsx +++ b/frontend/src/components/auth/SignInForm.tsx @@ -116,64 +116,6 @@ export default function SignInForm() {