This document provides step-by-step instructions for implementing and maintaining the authentication system in Odyssey.
- Firebase Google Authentication
- Middleware route protection
- Protected route components
- Authentication context
- Secure cookie management
- Logout functionality
- Token validation
All protected routes are now properly secured with double-layer protection:
- Server-side: Middleware checks
- Client-side: ProtectedRoute components
-
context/AuthContext.tsx- Global auth state management -
src/app/layout.tsx- Wrapped with AuthProvider
-
src/app/middleware.ts- Server-side protection -
components/ProtectedRoute.tsx- Client-side protection
-
src/app/Dashboard/page.tsx- Wrapped with ProtectedRoute -
src/app/Achievements/page.tsx- Wrapped with ProtectedRoute -
src/app/Habits/page.tsx- Wrapped with ProtectedRoute -
src/app/GritEngine/page.tsx- Wrapped with ProtectedRoute -
src/app/Inbox/page.tsx- Wrapped with ProtectedRoute -
src/app/Pages/page.tsx- Wrapped with ProtectedRoute -
src/app/Pages/[id]/page.tsx- Wrapped with ProtectedRoute
-
lib/cookies.ts- Cookie management functions -
components/NavBar.tsx- Added logout button
-
src/app/api/auth/verify/route.ts- Token verification -
src/app/api/auth/logout/route.ts- Logout handling
Add the new route to src/app/middleware.ts:
// Add to protected routes check
if (request.nextUrl.pathname.startsWith('/NewRoute') ||
request.nextUrl.pathname.startsWith('/ExistingRoute')) {
return NextResponse.redirect(new URL('/', request.url));
}
// Add to config matcher
export const config = {
matcher: [
'/NewRoute/:path*', // Add this line
// ... existing routes
]
};// src/app/NewRoute/page.tsx
import ProtectedRoute from '../../components/ProtectedRoute';
export default function NewRoute() {
return (
<ProtectedRoute>
<div>Your protected content here</div>
</ProtectedRoute>
);
}- Try accessing
/NewRoutewithout logging in - Verify redirect to home page
- Sign in and verify access works
- Test logout redirects properly
Symptoms: Can access protected routes without authentication
Solutions:
- Check middleware configuration
- Verify ProtectedRoute wrapper
- Clear browser cache
- Restart development server
Symptoms: Page keeps redirecting to login
Solutions:
- Check authentication context
- Verify cookie settings
- Check Firebase configuration
- Clear browser cookies
Symptoms: User signs in but gets redirected
Solutions:
- Check Firebase environment variables
- Verify AuthContext is working
- Check browser console for errors
- Verify cookie permissions
// In browser console
console.log('Auth Context:', useAuth());
console.log('Cookies:', document.cookie);
console.log('Firebase User:', auth.currentUser);- Check Network tab for redirects
- Look for middleware execution in console
- Verify cookie presence in Application tab
# Test without authentication
curl http://localhost:3000/Dashboard
# Should redirect to home page
# Test with valid token
curl -H "Cookie: token=valid_token" http://localhost:3000/Dashboard
# Should return page content'use client';
import { useAuth } from '../../context/AuthContext';
import ProtectedRoute from '../../components/ProtectedRoute';
export default function MyProtectedComponent() {
const { user } = useAuth();
return (
<ProtectedRoute>
<div>
<h1>Welcome, {user?.displayName}!</h1>
<p>This is protected content</p>
</div>
</ProtectedRoute>
);
}// Before: No protection
export default function MyComponent() {
return <div>Unprotected content</div>;
}
// After: With protection
import ProtectedRoute from '../components/ProtectedRoute';
export default function MyComponent() {
return (
<ProtectedRoute>
<div>Protected content</div>
</ProtectedRoute>
);
}import { useAuth } from '../context/AuthContext';
export default function CustomAuthComponent() {
const { user, loading } = useAuth();
if (loading) return <div>Loading...</div>;
if (!user) {
return <div>Please sign in to continue</div>;
}
// Custom authentication logic
if (user.email?.endsWith('@company.com')) {
return <div>Company users only</div>;
}
return <div>Access denied</div>;
}// β Wrong - Exposing user ID in client
const userId = user.uid; // Visible in browser
// β
Correct - Use server-side validation
const response = await fetch('/api/protected', {
headers: { 'Authorization': `Bearer ${token}` }
});// β Wrong - No validation
if (user) { /* allow access */ }
// β
Correct - Validate with middleware
// Middleware handles this automatically// β
Secure cookie configuration
setCookie('token', idToken, {
maxAge: 3600,
secure: true,
sameSite: 'strict'
});- Unauthenticated user redirected to login
- Authenticated user can access protected routes
- Logout clears session and redirects
- Token expiration triggers re-authentication
- Invalid tokens are rejected
- All protected routes require authentication
- Public routes remain accessible
- Middleware redirects work correctly
- ProtectedRoute components render properly
- Network errors handled gracefully
- Invalid tokens show appropriate messages
- Authentication failures don't crash app
- Loading states display correctly
- Check authentication logs
- Verify Firebase quotas
- Test authentication flow
- Review security alerts
- Update dependencies
- Review authentication policies
- Test with different browsers
- Performance optimization
- Security audit
- Code review
- User feedback analysis
- Feature enhancement planning
Document Version: 1.0.0
Last Updated: December 2024
Next Review: January 2025