I am building a website using React for the frontend and Laravel for the backend.
I wrote a React Context for authentication, which sends a request to the /api/user endpoint. This endpoint is protected with the auth:sanctum middleware.
However, I am constantly getting a 401 Unauthenticated response when calling /api/user.
I have followed all the recommended steps I found online, including:
Ensuring the SPA (React) and the backend are on the same domain or that the SPA domain is listed in SANCTUM_STATEFUL_DOMAINS.
Calling /sanctum/csrf-cookie before making authenticated requests.
Allowing the SPA URL in the CORS configuration.
Despite this, the problem persists.
What might I be missing? How can I resolve this and get Laravel Sanctum to recognize the session?
env
SANCTUM_STATEFUL_DOMAINS=localhost:5173
SESSION_DOMAIN=localhost
APP_FRONTEND_URL=http://localhost:5173
cors
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => [env('APP_FRONTEND_URL', 'http://localhost:3000')],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
authContext
import { createContext,useState,useEffect } from "react";
import api from "../axios";
export const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [user,setUser] = useState(null);
const fetchUser = async () => {
try {
const response = await api.get('/api/user');
setUser(response.data);
} catch (error) {
console.error("Error fetching user data:", error);
setUser(null);
}
}
const logout = async () => {
try {
await api.post('/api/logout');
setUser(null);
} catch (error) {
console.error("Error logging out:", error);
}
}
useEffect(() => {
api.get('/sanctum/csrf-cookie').then(fetchUser)},[]);
return (
<AuthContext.Provider value={{ user, fetchUser, logout }}>
{children}
</AuthContext.Provider>
);
}
api
import axios from 'axios'
const api = axios.create({
baseURL: 'http://localhost:8000',
withCredentials: true,
})
export default api
login
const [formData, setFormData] = useState({
email: "",
password: ""
});
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({
...formData,
[name]: value
});
}
const handleSubmit = (e) => {
e.preventDefault();
api.get('/sanctum/csrf-cookie')
.then(() => {
return api.post('/api/login', formData);
})
.then((response) => {
console.log('Logged in successfully:', response.data);
// Maybe redirect or fetch user
})
.catch((error) => {
console.error('Login failed:', error.response?.data || error.message);
alert("Login failed");
});
}