Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

stacker's avatar

User registration using Laravel Sanctum with fetch API call works without X-XSRF-TOKEN header, but with weird CORS error

I have a registration endpoint that works from Postman on http://localhost:8080/api/register

It also works from within a React app (using Next.js framework), but I get an error message:

register:1 Access to fetch at 'http://localhost:8080/api/register' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

However, I can see the new user is added to the database!

I am reading through Laravel's Sanctum docs, but they don't mention Access-Control-Allow-Origin headers, only Access-Control-Allow-Credentials which I set to true.

Also, I never used the X-XSRF-TOKEN that Laravel docs mention: https://laravel.com/docs/8.x/sanctum#spa-authentication

So how does it work without sending this token?

In my code, you can see I did try to create the csrf token, but it didn't work (I didn't see it in the browser's cookies):

export default function Register() {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');

    const handleSubmit = (evt) => {
        evt.preventDefault();

        const data = { email: email, password: password };

        fetch('http://localhost:8080/api/register', {
            method: 'POST',
            headers: {
                'Access-Control-Allow-Credentials': true,
                'Content-Type': 'application/json',
                'credentials': 'include',
            },
            body: JSON.stringify(data),
        })
            .then(response => response)
            .then(data => {
                console.log('Success:', data);
            })
            .catch((error) => {
                console.error(error);
            });
    }

    useEffect(() => {
        fetch('http://localhost:8080/sanctum/csrf-cookie') //doesn't work, doesn't create a cookie
    });

    return (
        <div> // form code here </div>
    )
}

So I am confused:

  1. Why isn't the token created in the way I tried to create it?
  2. How does it work without the token?
  3. Why does it give me this CORS error, yet still creates the user?
0 likes
2 replies
apex1's avatar

Don't have time to address all your concerns, but that is NOT how you want to use useEffect() for your use case. Without a dependency array, every time your component renders, the effect will run. So every keystroke when the user types in your input fields will trigger a re-render and the component will keep calling your backend. You want to use an empty array so the effect runs only on its first render, e.g.,

useEffect(() => {
	// code...
}, []);    **<= see this array**
1 like
stacker's avatar

Thank you! I actually changed that before seeing your answer. But then there is another issue: What happens if the single call to the API fails? It is called only once, so if it fails, it means I will never create the cookie? How should I handle failed fetch error so it will try to re-fetch?

Please or to participate in this conversation.