This document describes the authentication system implemented in the DisasterWatch web application, including user authentication flow, protected routes, and security considerations.
The DisasterWatch application implements a JWT-based authentication system with the following features:
- User registration and login
- Protected routes
- Token-based authentication
- Automatic token refresh
- Secure token storage
// Example registration flow
const register = async (userData) => {
const response = await api.post('/auth/register', userData);
const { token, user } = response.data;
login(user, token); // Store token and user data
};// Example login flow
const login = async (credentials) => {
const response = await api.post('/auth/login', credentials);
const { token, user } = response.data;
login(user, token); // Store token and user data
};- Tokens are stored in localStorage
- Automatic token validation
- Token expiration handling
- Secure token storage practices
// Higher-order component for protected routes
const withAuth = (WrappedComponent) => {
return (props) => {
const { isLoggedIn, isLoading } = useUser();
const router = useRouter();
useEffect(() => {
if (!isLoading && !isLoggedIn) {
router.push('/auth');
}
}, [isLoading, isLoggedIn, router]);
if (isLoading) {
return <Loading />;
}
return isLoggedIn ? <WrappedComponent {...props} /> : null;
};
};The following routes require authentication:
/dashboard/*/profile/*/resources/*/settings/*
These routes are accessible to all users:
//auth/*/map/about/contact
// UserContext provider
export const UserProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [isLoading, setIsLoading] = useState(true);
// Authentication check on mount
useEffect(() => {
checkAuth();
}, []);
// Check authentication status
const checkAuth = () => {
try {
const token = localStorage.getItem('token');
const storedUser = localStorage.getItem('user');
if (!token || !storedUser) {
handleLogout();
return;
}
const userData = JSON.parse(storedUser);
if (isTokenExpired(token)) {
handleLogout();
return;
}
setUser(userData);
setIsLoggedIn(true);
} catch (error) {
console.error('Auth check error:', error);
handleLogout();
} finally {
setIsLoading(false);
}
};
// Logout handler
const handleLogout = () => {
setUser(null);
setIsLoggedIn(false);
localStorage.removeItem('user');
localStorage.removeItem('token');
router.push('/auth');
};
// ... other context methods
};- JWT tokens are stored in localStorage
- Tokens are validated on each request
- Automatic token refresh mechanism
- Secure token storage practices
- Passwords are hashed on the server
- Password strength requirements
- Rate limiting on login attempts
- Secure password reset flow
- Automatic session timeout
- Multiple device handling
- Session invalidation on logout
- Secure session storage
- HTTPS enforcement
- CORS configuration
- Rate limiting
- Request validation
try {
await login(credentials);
} catch (error) {
if (error.response?.status === 401) {
// Handle invalid credentials
} else if (error.response?.status === 403) {
// Handle forbidden access
} else {
// Handle other errors
}
}const isTokenExpired = (token) => {
try {
const payload = JSON.parse(atob(token.split('.')[1]));
return payload.exp * 1000 < Date.now();
} catch {
return true;
}
};-
Token Management
- Store tokens securely
- Implement token refresh
- Handle token expiration
- Clear tokens on logout
-
Route Protection
- Use HOC for protected routes
- Implement loading states
- Handle authentication errors
- Redirect appropriately
-
Security
- Use HTTPS
- Implement rate limiting
- Validate user input
- Handle session timeouts
-
User Experience
- Show loading states
- Provide clear error messages
- Implement remember me
- Handle offline scenarios
describe('Authentication', () => {
it('should login successfully', async () => {
// Test login flow
});
it('should handle invalid credentials', async () => {
// Test error handling
});
it('should protect routes', () => {
// Test route protection
});
});-
Token Not Found
- Check localStorage
- Verify token storage
- Clear browser cache
-
Authentication Errors
- Check API responses
- Verify credentials
- Check network connectivity
-
Protected Route Issues
- Verify route configuration
- Check authentication state
- Review redirect logic
- Check the Issues page
- Create a new issue with detailed information
- Join our Discord community for support