From f98fd04191ec1bcf41847beef36a24a309fe7264 Mon Sep 17 00:00:00 2001 From: Alexander Borg Date: Fri, 19 Sep 2025 07:33:23 +0200 Subject: [PATCH] Fix jwt-token --- client/src/services/api.js | 54 ++++++++++++++++++++++++++++++---- management/src/services/api.js | 44 ++++++++++++++++++++------- server/middleware/auth.js | 22 +++++++++++--- 3 files changed, 100 insertions(+), 20 deletions(-) diff --git a/client/src/services/api.js b/client/src/services/api.js index 9f8cf82..9e5b441 100644 --- a/client/src/services/api.js +++ b/client/src/services/api.js @@ -49,13 +49,55 @@ api.interceptors.request.use( api.interceptors.response.use( (response) => response, (error) => { + console.log('๐Ÿšจ API Error Response:', { + status: error.response?.status, + data: error.response?.data, + config: { url: error.config?.url, method: error.config?.method } + }); + if (error.response?.status === 401 || error.response?.status === 403) { - // Check if it's a token-related error - const errorMessage = error.response?.data?.message || ''; - if (errorMessage.includes('token') || errorMessage.includes('expired') || - errorMessage.includes('invalid') || errorMessage.includes('required') || - error.response?.status === 401) { - console.warn('๐Ÿ” Authentication failed:', errorMessage); + const errorData = error.response.data; + const errorCode = errorData?.errorCode || errorData?.error; + + // Show user-friendly error message based on error type + let userMessage = errorData?.message || 'Authentication error'; + + // Categorize errors for better user experience + switch (errorCode) { + case 'TOKEN_EXPIRED': + userMessage = 'Your session has expired. Please log in again.'; + break; + case 'INVALID_TOKEN': + userMessage = 'Invalid authentication. Please log in again.'; + break; + case 'USER_NOT_FOUND': + userMessage = 'Your account was not found. Please contact support.'; + break; + case 'ACCOUNT_INACTIVE': + userMessage = 'Your account has been deactivated. Please contact support.'; + break; + case 'PERMISSION_DENIED': + userMessage = errorData.message; // Use the detailed permission message from backend + break; + default: + userMessage = errorData?.message || 'Authentication failed'; + } + + console.warn('๐Ÿ” Authentication/Authorization Error:', userMessage); + + // Dispatch error event for UI notification + window.dispatchEvent(new CustomEvent('authError', { + detail: { + message: userMessage, + errorCode, + type: error.response.status === 403 ? 'permission' : 'auth', + userRole: errorData?.userRole, + requiredRoles: errorData?.requiredRoles + } + })); + + // Only redirect to login for authentication errors, not permission errors + if (error.response.status === 401 || errorData?.redirectToLogin === true) { console.warn('๐Ÿ” Redirecting to login page'); // Clear authentication data diff --git a/management/src/services/api.js b/management/src/services/api.js index edf1e34..a346879 100644 --- a/management/src/services/api.js +++ b/management/src/services/api.js @@ -26,7 +26,7 @@ api.interceptors.request.use( api.interceptors.response.use( (response) => response, (error) => { - console.log('๐Ÿšจ API Response Error:', { + console.log('๐Ÿšจ Management API Error:', { status: error.response?.status, statusText: error.response?.statusText, data: error.response?.data, @@ -38,22 +38,45 @@ api.interceptors.response.use( if (error.response?.status === 401 || error.response?.status === 403) { const errorData = error.response.data; - console.warn('๐Ÿ” Authentication failed:', errorData?.message || 'Unknown error'); - console.log('๐Ÿ” Error details:', { + const errorCode = errorData?.errorCode || errorData?.error; + + console.warn('๐Ÿ” Management Authentication Error:', { error: errorData?.error, message: errorData?.message, + errorCode: errorCode, redirectToLogin: errorData?.redirectToLogin }); + // Show user-friendly error message based on error type + let userMessage = errorData?.message || 'Authentication error'; + + switch (errorCode) { + case 'TOKEN_EXPIRED': + userMessage = 'Your management session has expired. Please log in again.'; + break; + case 'INVALID_TOKEN': + userMessage = 'Invalid management authentication. Please log in again.'; + break; + case 'INSUFFICIENT_PERMISSIONS': + userMessage = errorData.message; // Use detailed message from backend + break; + default: + if (errorData?.message?.includes('management token')) { + userMessage = 'Your management session has expired. Please log in again.'; + } + } + + // Show error message (you can integrate with your notification system) + console.error('Management Error:', userMessage); + // Clear authentication data - console.log('๐Ÿงน Clearing authentication data...'); + console.log('๐Ÿงน Clearing management authentication data...'); localStorage.removeItem('management_token') localStorage.removeItem('management_user') - // Check if the backend indicates we should redirect to login - if (errorData?.redirectToLogin !== false) { - console.log('๐Ÿ”„ Redirecting to login page...'); - // Use both methods to ensure redirect works + // Only redirect to login for authentication errors, not permission errors + if (error.response.status === 401 || errorData?.redirectToLogin !== false) { + console.log('๐Ÿ”„ Redirecting to management login page...'); try { if (window.location.pathname !== '/login') { console.log('๐Ÿ”„ Current path:', window.location.pathname, '- redirecting...'); @@ -63,11 +86,12 @@ api.interceptors.response.use( } } catch (e) { console.error('Failed to redirect via location.href:', e); - // Fallback: try replace window.location.replace('/login'); } } else { - console.log('๐Ÿšซ Redirect to login disabled by backend response'); + console.log('๐Ÿšซ Permission error - not redirecting to login'); + // For permission errors, you might want to show a modal or toast notification + // instead of redirecting } } return Promise.reject(error) diff --git a/server/middleware/auth.js b/server/middleware/auth.js index 0911faf..32aaac2 100644 --- a/server/middleware/auth.js +++ b/server/middleware/auth.js @@ -67,14 +67,20 @@ async function authenticateToken(req, res, next) { if (!user) { return res.status(401).json({ success: false, - message: 'User not found' + message: 'User account not found. Please contact support.', + error: 'USER_NOT_FOUND', + errorCode: 'USER_NOT_FOUND', + redirectToLogin: true }); } if (!user.is_active) { return res.status(401).json({ success: false, - message: 'User account is inactive' + message: 'Your account has been deactivated. Please contact support.', + error: 'ACCOUNT_DEACTIVATED', + errorCode: 'ACCOUNT_INACTIVE', + redirectToLogin: true }); } @@ -158,7 +164,10 @@ function requireRole(roles) { if (!req.user) { return res.status(401).json({ success: false, - message: 'Authentication required' + message: 'Authentication required', + error: 'NO_AUTH', + errorCode: 'AUTH_REQUIRED', + redirectToLogin: true }); } @@ -166,7 +175,12 @@ function requireRole(roles) { if (!userRoles.includes(req.user.role)) { return res.status(403).json({ success: false, - message: 'Insufficient permissions' + message: `Access denied. This action requires ${userRoles.join(' or ')} permissions, but you have ${req.user.role} permissions.`, + error: 'INSUFFICIENT_PERMISSIONS', + errorCode: 'PERMISSION_DENIED', + userRole: req.user.role, + requiredRoles: userRoles, + redirectToLogin: false // Don't redirect for permission issues }); }