1

I have a Next JS frontend and Laravel 9 as backend. Created APIs and tested them on the postman. All of the API's working fine without any issues.

The Problem

So I have created a Nextjs file with a form and posted data using Axios. I am getting Error: Request failed with status code 419.

Tried

There are multiple answers available on StackOverflow for similar questions. I followed the answers but nothing worked for the problem.

  1. Changed VerifyCsrfToken.php code to disable the csrf protection. (i want to keep the csrf)

  2. Tried adding the csrf cookie using the headers option in Axios. (Axios POST to Laravel API results in 419 error)

  3. Generated key using (PHP artisan key: generate)

  4. Added Session domain

  5. added route in the web middleware

Route::group(['middleware' => ['api']], function () {

    // our routes

});

What's working ?

  1. Allowing all domains in VerifyCsrfToken.php is working.

I want to get csrf token

`const csrf = () => axios.get('/sanctum/csrf-cookie')'

i am getting empty value for csrf token / csrf cookie. and found no accepted answer to the request failed with status code 419.

Does anyone know what I am doing wrong?

3
  • How to work with the CSRF really depends on your app. For example I have a script in my main page layout like <script>window.csrfToken = "{{csrf_token()}}";</script> and whenever i POST something to my backend I always need to add field _token: window.csrfToken but there's literally hundreds of ways to get this to work as long as you pass the token from your backend to your frontend somehow and then remember to send it back to the backend it should work. Commented Oct 23, 2022 at 10:41
  • can you please share a way to add csfr using nextjs frontend for laravel backend. Commented Oct 23, 2022 at 11:28
  • 1
    If you are not already, use Sanctum in your backend and set it up such that const csrf = () => axios.get('/sanctum/csrf-cookie')' works i.e. set it up for SPA authentication. If you do already use Sanctum and /sanctum/csrf-cookie doesn't work then you probably misconfigured it Commented Oct 23, 2022 at 16:23

5 Answers 5

1

Try changing the middleware from web to api.

Route::group(['middleware' => ['api']], function () {

    // our routes

});
Sign up to request clarification or add additional context in comments.

1 Comment

tried. but not fixed the problem. is there any wasy to get and add laravel csrf token ?
1

If you don't have the csrf token in your frontend, and want to disable the check on that specific route, you need to add the route to $except array in your App\Http\Middleware\VerifyCsrfToken.php class:

<?php namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
  protected $except = [
    'your route here',
  ];
}

1 Comment

how i can get the laravel csrf in the next js frontend, if i want to get and pass using the form / axios header.
1

I don't know Nextjs, but basically you can put Laravel CSRF token at HTML document meta tag like this

<meta name="csrf-token" content="{{ csrf_token() }}" />

then you can access it using plain javascript like this

var csrf = document.querySelector('meta[name="csrf-token"]').content;

Comments

1

you can use rewrite its works for me

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: false,

  async redirects() {
    return []
  },

  rewrites: async () => {
    return {


      fallback: [
        {
          source: '/api/:path*',
          destination: 'http://domain.test/:path*'
        },

      ],
    }
  }
};

export default nextConfig;

and in axios config

import Axios from 'axios'

const axios = Axios.create({
  baseURL: http://localhost:3000/api,
  headers: {
    'X-Requested-With': 'XMLHttpRequest',
  },
  withCredentials: true,
  withXSRFToken: true
})

export default axios

Comments

0

As per the documentation of laravel :

Do these 3 changes in Laravel

  1. Update the cors policy (config/cors.php)

From : 'supports_credentials' => false,

To: 'supports_credentials' => true,

  1. Add the line in (resources/js/bootstrap.js)

axios.defaults.withCredentials = true;

  1. Add backend and frontend url in .env file in laravel
APP_URL=http://localhost:8000
FRONTEND_URL=http://localhost:3000

Now do the following cahnges in NEXT JS app.

  1. Add .env.local file at the root and add the following code. NEXT_PUBLIC_BACKEND_URL=http://localhost:8000'

  2. Install axios using npm i axios

  3. Import CSRF Token using AXIOS before posting the data using axios then post form data using axios.

Here is the sample code to send or get data

import React, { useEffect, useState } from 'react';
import axios from 'axios';

//optional toastify library
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

export default function index({data}) {

//console.log(data); 

  //setting the state (getting form data into veriable)
  const [title, setTitle] = useState('')
  const [desc, setDesc] = useState('')

  
  // preventing default and showing the data in console
  const formSubmit = async (e) => {
  e.preventDefault();
  console.log(title ,desc);

      // setting csrf token
       await axios.get('http://localhost:8000/sanctum/csrf-cookie').then(getcsrvf => {
                
          //console.log(getcsrvf);
            
                 // posting the data using axios / creating the data.
                  axios.post('http://localhost:8000/api/post', {title,desc})
                  .then(function (response) {
                    //alert(response.data.message);
                    
                   toast(response.data.message);
                    
                    console.log(response);
                  })
                  .catch(function (error) {
                    //console.log(error);
                  });
          });
} 


  return (

// bootstrap installed

<div className=' pt-5'>
<div className='container'>

//basic jsx form

<form onSubmit={formSubmit}> 

 <div className='mb-2'> 

{/* onChange={(e)=>{setName(e.target.value)}} */}

<input type="text" onChange={(e) => {setTitle(e.target.value)}} value={title} className="form-control mb-2 py-2" placeholder="title" name="title" id='title' />

</div>  

<div className='mb-2'>
<input type="text" onChange={(e) => {setDesc(e.target.value)}} value={desc} className="form-control mb-2 py-2" placeholder="desc" name="desc" id='desc' />
</div>  


<div className='mb-2'>
<button className='btn btn-primary'>Submit</button>
</div>  
</form> 

</div>


<hr/>
//looping the post data

{data.post.map((post, i)=>{
  return (
    <div className='container' key={i}>
      <h3>{post.title}</h3>
      <p>{post.desc}</p>
      <hr/>
    </div>
  )
})}


<ToastContainer position="top-center" pauseOnHover="false"/>

</div>
  )
}

// Getting the records // reading the data

export async function getServerSideProps() {
 
const res = await fetch("http://localhost:8000/api/post")
const data = await res.json()

return{
  props: {
    data
  }
}
}

Note : Pleae change http://localhost:8000 as your laravle url and http://localhost:3000 as per your frontend url.

The above solution worked for me.

2 Comments

I've done all of those steps and it still does not work on production. It works on local dev only. My laravel backend and NextJS frontend are on two different domains.
should we fetch sanctum/csrf-cookie before doing post method on all enpoints?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.