183 lines
7.1 KiB
Markdown
183 lines
7.1 KiB
Markdown
# 404 and Session Expiration Fixes
|
|
|
|
## Issues Addressed
|
|
|
|
1. **404 Error on Expenses Page** - The expenses page was returning a 404 error
|
|
2. **Session Expiration After 404** - Users were getting logged out after encountering the 404 error
|
|
3. **Immediate Session Expiration** - Users were getting logged out immediately after logging in
|
|
4. **External Service 401 Errors** - 401 errors from external services (CMS, database) were logging users out
|
|
|
|
## Root Cause Analysis
|
|
|
|
### 404 Error Cause
|
|
- The expenses page was missing the authorization middleware configuration
|
|
- The dashboard layout referenced in the page metadata didn't exist
|
|
- Nuxt wasn't properly configured to use layouts
|
|
|
|
### Session Expiration Cause
|
|
- The authentication middleware was incorrectly clearing the session cache on ALL errors (including 404s)
|
|
- This caused a valid session to be invalidated when encountering any page error
|
|
|
|
### Immediate Logout Cause
|
|
- The authorization middleware was making its own API call, bypassing the session cache
|
|
- The auth refresh plugin's 2-minute periodic validation was conflicting with the 3-minute session cache
|
|
- Multiple concurrent session checks were causing race conditions
|
|
|
|
### External Service 401 Cause
|
|
- The auth error handler was treating ANY 401 error as a session expiration
|
|
- When the CMS (`cms.portnimara.dev`) returned 401, it triggered a logout
|
|
- The handler didn't distinguish between auth API errors and external service errors
|
|
|
|
## Fixes Implemented
|
|
|
|
### 1. Fixed Expenses Page Metadata
|
|
**File**: `pages/dashboard/expenses.vue`
|
|
|
|
Added proper middleware configuration:
|
|
```javascript
|
|
definePageMeta({
|
|
middleware: ['authentication', 'authorization'],
|
|
layout: 'dashboard',
|
|
roles: ['sales', 'admin']
|
|
});
|
|
```
|
|
|
|
This ensures:
|
|
- Authentication is checked first
|
|
- Authorization checks for sales/admin roles
|
|
- Proper layout is applied
|
|
|
|
### 2. Fixed Authentication Middleware
|
|
**File**: `middleware/authentication.ts`
|
|
|
|
Updated error handling to only clear cache on actual auth errors:
|
|
```javascript
|
|
onResponseError({ response }) {
|
|
// Clear cache only on actual auth errors, not 404s or other errors
|
|
if (response.status === 401) {
|
|
console.log('[MIDDLEWARE] Unauthorized error detected, clearing cache')
|
|
sessionManager.clearCache();
|
|
delete nuxtApp.payload.data?.authState;
|
|
} else if (response.status === 403) {
|
|
console.log('[MIDDLEWARE] Forbidden error detected, partial cache clear')
|
|
// Don't clear cache on 403 as user is authenticated but lacks permissions
|
|
}
|
|
// Ignore 404s and other errors - they're not authentication issues
|
|
}
|
|
```
|
|
|
|
### 3. Enabled Layout Support
|
|
**File**: `app.vue`
|
|
|
|
Updated to support layouts:
|
|
```vue
|
|
<template>
|
|
<NuxtPwaManifest />
|
|
<NuxtLayout>
|
|
<NuxtPage />
|
|
</NuxtLayout>
|
|
<GlobalToast />
|
|
</template>
|
|
```
|
|
|
|
### 4. Created Dashboard Layout
|
|
**File**: `layouts/dashboard.vue`
|
|
|
|
Created a full dashboard layout with:
|
|
- Navigation drawer with role-based menu items
|
|
- App bar showing user info and role badges
|
|
- Proper logout functionality
|
|
- Responsive design with rail mode
|
|
- Safe auth state access to prevent initialization errors
|
|
|
|
### 5. Fixed Authorization Middleware
|
|
**File**: `middleware/authorization.ts`
|
|
|
|
Updated to use cached auth state instead of making API calls:
|
|
```javascript
|
|
// Get auth state from authentication middleware (already cached)
|
|
const nuxtApp = useNuxtApp();
|
|
const authState = nuxtApp.payload?.data?.authState;
|
|
```
|
|
|
|
This prevents:
|
|
- Duplicate API calls
|
|
- Race conditions between middlewares
|
|
- Session cache conflicts
|
|
|
|
### 6. Adjusted Auth Refresh Plugin
|
|
**File**: `plugins/01.auth-refresh.client.ts`
|
|
|
|
- Changed periodic validation from 2 to 5 minutes to avoid conflicts with 3-minute cache
|
|
- Added failure counting - only logs out after 3 consecutive failures
|
|
- Increased random offset to prevent thundering herd
|
|
|
|
### 7. Fixed Auth Error Handler
|
|
**File**: `plugins/02.auth-error-handler.client.ts`
|
|
|
|
Updated to only handle 401/403 errors from application endpoints:
|
|
```javascript
|
|
// Only handle authentication errors from our own API endpoints
|
|
const isAuthEndpoint = response.url && (
|
|
response.url.includes('/api/auth/') ||
|
|
response.url.includes('/api/') && !response.url.includes('cms.portnimara.dev') && !response.url.includes('database.portnimara.com')
|
|
)
|
|
|
|
// Handle authentication errors (401, 403) only from our API
|
|
if ((response.status === 401 || response.status === 403) && isAuthEndpoint) {
|
|
// Clear auth and redirect
|
|
} else if (response.status === 401 && !isAuthEndpoint) {
|
|
console.log('[AUTH_ERROR_HANDLER] Ignoring 401 from external service:', response.url)
|
|
// Don't clear auth for external service 401s
|
|
}
|
|
```
|
|
|
|
This prevents external service authentication errors from logging users out.
|
|
|
|
## Expected Results
|
|
|
|
1. **Expenses page should now load properly** for users with sales or admin roles
|
|
2. **404 errors won't cause session expiration** - only actual authentication failures (401) will clear the session
|
|
3. **Better error handling** - 403 errors (insufficient permissions) will redirect to dashboard with a message instead of logging out
|
|
4. **Consistent layout** across all dashboard pages
|
|
5. **No immediate logout** - Session checks are properly coordinated and cached
|
|
6. **Stable session management** - No conflicts between different auth checking mechanisms
|
|
7. **External service errors ignored** - 401 errors from CMS or database won't log users out
|
|
|
|
## Testing Steps
|
|
|
|
1. Log in with a user that has sales or admin role
|
|
2. Navigate to `/dashboard/expenses`
|
|
3. Verify the page loads without 404
|
|
4. If you don't have the required role, you should be redirected to dashboard with an error message (not logged out)
|
|
5. Try navigating to a non-existent page - you should get a 404 but remain logged in
|
|
|
|
## Additional Improvements
|
|
|
|
- The authorization middleware now stores error messages that are displayed via toast
|
|
- The authorization middleware uses cached auth state instead of making API calls
|
|
- The dashboard layout shows the current user and their role with safe access patterns
|
|
- Navigation menu dynamically shows/hides items based on user roles
|
|
- Session validation continues to work with the 3-minute cache + jitter to prevent race conditions
|
|
- Auth refresh plugin runs validation every 5 minutes to avoid cache conflicts
|
|
- Multiple failure tolerance prevents transient issues from logging users out
|
|
- Auth error handler differentiates between app and external service errors
|
|
|
|
## Timing Configuration Summary
|
|
|
|
- **Session Cache**: 3 minutes (with 0-10 second jitter)
|
|
- **Auth Refresh Validation**: Every 5 minutes (with 0-10 second offset)
|
|
- **Token Refresh**: 5 minutes before token expiry
|
|
- **Failure Tolerance**: 3 consecutive failures before logout
|
|
|
|
This configuration ensures no timing conflicts between different auth mechanisms.
|
|
|
|
## External Service Integration
|
|
|
|
The auth error handler now properly handles errors from external services:
|
|
- **CMS errors** (cms.portnimara.dev) - 401 errors are logged but don't trigger logout
|
|
- **Database errors** (database.portnimara.com) - 401 errors are logged but don't trigger logout
|
|
- **App API errors** (/api/*) - 401/403 errors still trigger logout as expected
|
|
|
|
This allows the app to gracefully handle authentication failures with integrated services without disrupting the user's main session.
|