Fix jwt-token
This commit is contained in:
@@ -49,13 +49,55 @@ api.interceptors.request.use(
|
|||||||
api.interceptors.response.use(
|
api.interceptors.response.use(
|
||||||
(response) => response,
|
(response) => response,
|
||||||
(error) => {
|
(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) {
|
if (error.response?.status === 401 || error.response?.status === 403) {
|
||||||
// Check if it's a token-related error
|
const errorData = error.response.data;
|
||||||
const errorMessage = error.response?.data?.message || '';
|
const errorCode = errorData?.errorCode || errorData?.error;
|
||||||
if (errorMessage.includes('token') || errorMessage.includes('expired') ||
|
|
||||||
errorMessage.includes('invalid') || errorMessage.includes('required') ||
|
// Show user-friendly error message based on error type
|
||||||
error.response?.status === 401) {
|
let userMessage = errorData?.message || 'Authentication error';
|
||||||
console.warn('🔐 Authentication failed:', errorMessage);
|
|
||||||
|
// 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');
|
console.warn('🔐 Redirecting to login page');
|
||||||
|
|
||||||
// Clear authentication data
|
// Clear authentication data
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ api.interceptors.request.use(
|
|||||||
api.interceptors.response.use(
|
api.interceptors.response.use(
|
||||||
(response) => response,
|
(response) => response,
|
||||||
(error) => {
|
(error) => {
|
||||||
console.log('🚨 API Response Error:', {
|
console.log('🚨 Management API Error:', {
|
||||||
status: error.response?.status,
|
status: error.response?.status,
|
||||||
statusText: error.response?.statusText,
|
statusText: error.response?.statusText,
|
||||||
data: error.response?.data,
|
data: error.response?.data,
|
||||||
@@ -38,22 +38,45 @@ api.interceptors.response.use(
|
|||||||
|
|
||||||
if (error.response?.status === 401 || error.response?.status === 403) {
|
if (error.response?.status === 401 || error.response?.status === 403) {
|
||||||
const errorData = error.response.data;
|
const errorData = error.response.data;
|
||||||
console.warn('🔐 Authentication failed:', errorData?.message || 'Unknown error');
|
const errorCode = errorData?.errorCode || errorData?.error;
|
||||||
console.log('🔐 Error details:', {
|
|
||||||
|
console.warn('🔐 Management Authentication Error:', {
|
||||||
error: errorData?.error,
|
error: errorData?.error,
|
||||||
message: errorData?.message,
|
message: errorData?.message,
|
||||||
|
errorCode: errorCode,
|
||||||
redirectToLogin: errorData?.redirectToLogin
|
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
|
// Clear authentication data
|
||||||
console.log('🧹 Clearing authentication data...');
|
console.log('🧹 Clearing management authentication data...');
|
||||||
localStorage.removeItem('management_token')
|
localStorage.removeItem('management_token')
|
||||||
localStorage.removeItem('management_user')
|
localStorage.removeItem('management_user')
|
||||||
|
|
||||||
// Check if the backend indicates we should redirect to login
|
// Only redirect to login for authentication errors, not permission errors
|
||||||
if (errorData?.redirectToLogin !== false) {
|
if (error.response.status === 401 || errorData?.redirectToLogin !== false) {
|
||||||
console.log('🔄 Redirecting to login page...');
|
console.log('🔄 Redirecting to management login page...');
|
||||||
// Use both methods to ensure redirect works
|
|
||||||
try {
|
try {
|
||||||
if (window.location.pathname !== '/login') {
|
if (window.location.pathname !== '/login') {
|
||||||
console.log('🔄 Current path:', window.location.pathname, '- redirecting...');
|
console.log('🔄 Current path:', window.location.pathname, '- redirecting...');
|
||||||
@@ -63,11 +86,12 @@ api.interceptors.response.use(
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to redirect via location.href:', e);
|
console.error('Failed to redirect via location.href:', e);
|
||||||
// Fallback: try replace
|
|
||||||
window.location.replace('/login');
|
window.location.replace('/login');
|
||||||
}
|
}
|
||||||
} else {
|
} 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)
|
return Promise.reject(error)
|
||||||
|
|||||||
@@ -67,14 +67,20 @@ async function authenticateToken(req, res, next) {
|
|||||||
if (!user) {
|
if (!user) {
|
||||||
return res.status(401).json({
|
return res.status(401).json({
|
||||||
success: false,
|
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) {
|
if (!user.is_active) {
|
||||||
return res.status(401).json({
|
return res.status(401).json({
|
||||||
success: false,
|
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) {
|
if (!req.user) {
|
||||||
return res.status(401).json({
|
return res.status(401).json({
|
||||||
success: false,
|
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)) {
|
if (!userRoles.includes(req.user.role)) {
|
||||||
return res.status(403).json({
|
return res.status(403).json({
|
||||||
success: false,
|
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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user