AuthContext.js•4.07 kB
import React, { createContext, useContext, useState, useEffect } from 'react';
import { jwtDecode } from 'jwt-decode';
import axios from 'axios';
// Create auth context
const AuthContext = createContext();
// Custom hook to use auth context
export const useAuth = () => useContext(AuthContext);
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [token, setToken] = useState(localStorage.getItem('token'));
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
// Set up axios interceptor for authentication
useEffect(() => {
const interceptor = axios.interceptors.request.use(
(config) => {
if (token) {
config.headers.Authorization = token;
}
return config;
},
(error) => Promise.reject(error)
);
return () => {
axios.interceptors.request.eject(interceptor);
};
}, [token]);
// Check if token is valid and get user data
useEffect(() => {
const verifyToken = async () => {
setIsLoading(true);
setError(null);
// If no token, not authenticated
if (!token) {
setIsAuthenticated(false);
setUser(null);
setIsLoading(false);
return;
}
try {
// Check if token is expired
const decodedToken = jwtDecode(token);
const currentTime = Date.now() / 1000;
if (decodedToken.exp < currentTime) {
// Token expired
logout();
setIsLoading(false);
return;
}
// Validate token with backend
const response = await axios.get('/api/auth/validate');
if (response.data.success) {
setUser(response.data.user);
setIsAuthenticated(true);
} else {
logout();
}
} catch (error) {
console.error('Token validation error:', error);
setError('Session expired or invalid');
logout();
} finally {
setIsLoading(false);
}
};
verifyToken();
}, [token]);
// Login function
const login = async (credentials) => {
setIsLoading(true);
setError(null);
try {
const response = await axios.post('/api/auth/login', credentials);
if (response.data.success) {
const { token, user } = response.data;
setToken(token);
setUser(user);
setIsAuthenticated(true);
localStorage.setItem('token', token);
return { success: true };
} else {
throw new Error(response.data.message || 'Login failed');
}
} catch (error) {
setError(error.response?.data?.message || error.message || 'Login failed');
return {
success: false,
error: error.response?.data?.message || error.message || 'Login failed'
};
} finally {
setIsLoading(false);
}
};
// Register function
const register = async (userData) => {
setIsLoading(true);
setError(null);
try {
const response = await axios.post('/api/auth/register', userData);
if (response.data.success) {
return { success: true };
} else {
throw new Error(response.data.message || 'Registration failed');
}
} catch (error) {
setError(error.response?.data?.message || error.message || 'Registration failed');
return {
success: false,
error: error.response?.data?.message || error.message || 'Registration failed'
};
} finally {
setIsLoading(false);
}
};
// Logout function
const logout = () => {
setToken(null);
setUser(null);
setIsAuthenticated(false);
localStorage.removeItem('token');
};
// Context value
const contextValue = {
user,
token,
isAuthenticated,
isLoading,
error,
login,
register,
logout
};
return (
<AuthContext.Provider value={contextValue}>
{children}
</AuthContext.Provider>
);
};