Authentication
Jumbo React Vite ships a complete authentication context with cookie-based session persistence and a HOC for protecting routes. The included auth service is a mock — it is designed to be swapped for your real backend with minimal changes.
Architecture
Authentication state is managed by AuthProvider in src/components/AuthProvider/. It exposes
an AuthContext with four values:
interface AuthContextType {
isAuthenticated: boolean;
loading: boolean;
login: (credentials: { email: string; password: string }) => Promise<unknown>;
logout: () => void;
}The provider is mounted at the top of the app in App.tsx, wrapping the entire component tree.
How the mock service works
The included mock auth service simulates a network request with a setTimeout. It accepts a single
hardcoded credential pair and stores the session in a browser cookie:
// src/components/AuthProvider/AuthProvider.tsx (simplified)
const iAuthService = async (email: string, password: string) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (email === 'demo@example.com' && password === 'zab#723') {
resolve({ token: 'auth-user', email, password });
} else {
reject('Invalid email or password');
}
}, 3000);
});
};On successful login, the session object is JSON-encoded, URL-encoded, and stored in the auth-user
cookie for one day. On page reload, useEffect reads the cookie and restores isAuthenticated.
Using the auth hook
Any component inside AuthProvider can read auth state and call auth methods:
import { useAuth } from '@/hooks/useAuth';
export function ProfileMenu() {
const { isAuthenticated, loading, logout } = useAuth();
if (loading) return <Spinner />;
return isAuthenticated
? <Button onClick={logout}>Sign out</Button>
: null;
}Route protection with withAuth
The withAuth HOC in src/hoc/withAuth.tsx guards any component from unauthenticated access:
// src/hoc/withAuth.tsx
const withAuth = (Component: React.ComponentType) => {
return (): React.JSX.Element | null => {
const { isAuthenticated, loading } = useAuth();
if (loading) return <Spinner />;
if (!isAuthenticated) return <Navigate to='/auth/login-1' />;
return <Component />;
};
};Apply it in the route definition via the Page wrapper:
// src/routes/demo-routes.tsx
{
path: '/dashboards/misc',
element: <Page Component={MiscPage} hoc={withAuth} />,
},Auth pages
The following auth pages are included under the /auth prefix:
| Route | Component | Description |
|---|---|---|
/auth/login-1 | Login1Page | Default login page (form + hero image) |
/auth/login-2 | Login2Page | Alternate login layout |
/auth/signup-1 | Signup1Page | Registration page |
/auth/signup-2 | Signup2Page | Alternate registration layout |
/auth/forgot-password | ForgotPasswordPage | Password reset request |
/auth/reset-password | ResetPasswordPage | New password entry |
Replacing the mock with a real backend
Create your auth service
Replace
iAuthServiceinsideAuthProvider.tsxwith a real API call:typescript// src/components/AuthProvider/AuthProvider.tsx const loginUser = async (email: string, password: string) => { const response = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }), }); if (!response.ok) throw new Error('Invalid credentials'); return response.json(); // expects { token: string, ... } };Store the token securely
Replace the cookie storage with
httpOnlycookies set by the server, or store the JWT in memory and refresh via a silent request. UpdateAuthProviderto read the token from its new location in theuseEffectboot check.Add token to API requests
Create an API client that attaches the authorization header to every request:
typescript// src/services/apiClient.ts export async function apiFetch(url: string, options?: RequestInit) { const token = getCookieValue('auth-user')?.token; return fetch(url, { ...options, headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', ...options?.headers, }, }); }Update the logout handler
Call your server's logout endpoint to invalidate the session before clearing the cookie:
typescriptconst logout = async () => { await fetch('/api/auth/logout', { method: 'POST' }); eraseCookie('auth-user'); setIsAuthenticated(false); };
The mock service accepts a hardcoded email and password. Remove iAuthService entirely before
deploying to any environment accessible by users. Store real credentials only server-side and
transmit session tokens over HTTPS.