Overview
The AuthContext manages user authentication, login state, and role-based access control. It handles login/logout operations and persists authentication state to localStorage.
Source: ~/workspace/source/src/context/AuthContext.jsx
Setup
Wrap your application with the AuthProvider (must be inside Router):
import { BrowserRouter } from 'react-router-dom';
import { AuthProvider } from './context/AuthContext';
function App() {
return (
<BrowserRouter>
<AuthProvider>
{/* Your app components */}
</AuthProvider>
</BrowserRouter>
);
}
Usage
Use the useAuth custom hook to access authentication context:
import { useAuth } from '../context/AuthContext';
function MyComponent() {
const { isAuthenticated, role, handleSubmit } = useAuth();
// Use auth methods and state
}
State Properties
isAuthenticated
Whether a user is currently logged in. Synced with localStorage on mount.
role
Current user’s role. Either 'admin' or 'cliente'. Empty string when not authenticated.
email
Email input value for the login form.
setEmail
Update the email input value.
password
Password input value for the login form.
setPassword
Update the password input value.
errors
Validation and authentication error messages. Keys: email, password.
// Example errors object
{
email: "Email es requerido",
password: "Password es requerido"
}
// Or authentication error
{
email: "credenciales invalidas"
}
setErrors
Update error messages. Useful for clearing errors.
setIsAuth
Manually set authentication state. Used for logout.
Methods
handleSubmit
Processes login form submission, validates credentials, and redirects based on user role.
Form submit event. Will be prevented from default behavior.
Behavior:
- Validates email and password are not empty
- Fetches user data from
data/users.json
- Matches credentials against user database
- Sets authentication state and role
- Saves to localStorage:
isAuth and role
- Redirects:
- Admin users →
/admin
- Regular users →
/
Validation Errors:
- Empty email:
"Email es requerido"
- Empty password:
"Password es requerido"
- Invalid credentials:
"credenciales invalidas"
- Server error:
"Algo salió mal. Por favor, inténtalo de nuevo más tarde."
Example:
import { useAuth } from '../context/AuthContext';
import { Link } from 'react-router-dom';
const Login = () => {
const { errors, email, setEmail, password, setPassword, handleSubmit } = useAuth();
return (
<div className="container my-5" style={{ maxWidth: '400px' }}>
<form onSubmit={handleSubmit} noValidate>
<h2 className="text-center mb-4">Iniciar Sesión</h2>
<div className="mb-3">
<label htmlFor="formBasicEmail" className="form-label">
Email
</label>
<input
id="formBasicEmail"
type="email"
placeholder="Ingrese su email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className={`form-control ${errors.email ? 'is-invalid' : ''}`}
/>
{errors.email && <div className="invalid-feedback">{errors.email}</div>}
</div>
<div className="mb-3">
<label htmlFor="formBasicPassword" className="form-label">
Contraseña
</label>
<input
id="formBasicPassword"
type="password"
placeholder="Ingrese su contraseña"
value={password}
onChange={(e) => setPassword(e.target.value)}
className={`form-control ${errors.password ? 'is-invalid' : ''}`}
/>
{errors.password && <div className="invalid-feedback">{errors.password}</div>}
</div>
<button type="submit" className="btn btn-primary w-100">
Enviar
</button>
<p className="text-center mt-3">
<Link to="/" className="text-primary">← Volver al inicio.</Link>
</p>
</form>
</div>
);
};
export default Login;
Authentication Flow
Login Process
- User enters email and password
- Form submission calls
handleSubmit(e)
- Client-side validation checks for empty fields
- Fetches user database from
data/users.json
- Searches for matching email and password
- On success:
- Sets
isAuthenticated = true
- Sets
role based on user data
- Saves to localStorage
- Navigates to appropriate route
- On failure:
- Sets error message
- User remains on login page
Auto-Login on Mount
The context checks localStorage on mount:
useEffect(() => {
const isAuthenticated = localStorage.getItem('isAuth') === 'true'
const userRole = localStorage.getItem('role') || '';
if (isAuthenticated && userRole === 'admin') {
setIsAuth(true)
setRole(userRole)
navigate('/admin')
}
else if (isAuthenticated && userRole === 'cliente') {
setIsAuth(true)
setRole(userRole)
navigate('/')
}
}, [])
This enables persistent sessions across page refreshes.
Logout Implementation
To implement logout, clear localStorage and reset auth state:
import { useAuth } from '../context/AuthContext';
import { useNavigate } from 'react-router-dom';
function LogoutButton() {
const { setIsAuth } = useAuth();
const navigate = useNavigate();
const handleLogout = () => {
localStorage.removeItem('isAuth');
localStorage.removeItem('role');
setIsAuth(false);
navigate('/login');
};
return (
<button onClick={handleLogout}>Cerrar Sesión</button>
);
}
Protected Routes
Use authentication state to protect routes:
import { useAuth } from './context/AuthContext';
import { Navigate } from 'react-router-dom';
function App() {
const { isAuthenticated, role } = useAuth();
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
{/* Admin-only route */}
<Route
path="/admin"
element={
isAuthenticated && role === 'admin'
? <Admin />
: <Navigate to="/login" />
}
/>
</Routes>
);
}
User Data Structure
The authentication system expects a data/users.json file with this structure:
Security Notes
This implementation stores passwords in plain text and uses client-side validation only. This is suitable for demonstration purposes but NOT for production use.For production:
- Implement server-side authentication
- Hash passwords with bcrypt or similar
- Use secure tokens (JWT)
- Implement proper session management
- Add HTTPS/TLS encryption
Complete Implementation Example
import { useAuth } from './context/AuthContext';
import { Routes, Route, Navigate } from 'react-router-dom';
import Login from './layout/Login';
import Admin from './layout/Admin';
import Home from './layout/Home';
function App() {
const { isAuthenticated, role } = useAuth();
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route
path="/admin"
element={
isAuthenticated && role === 'admin'
? <Admin />
: <Navigate to="/login" />
}
/>
</Routes>
);
}
export default App;