Ad

Disable Laravel CSRF Protection For /api Routes When Consuming API With JavaScript

I have a Laravel backend, and React frontend. For development, React runs on localhost:3000 and Laravel on localhost:8080, so I had to allow Cors.

I have set up Passport successfuly and am able to Consume my API with JavaScript.

But on every request, I have to include the X-CSRF-TOKEN to access protected API routes, which works, but for development I'd like to disable CSRF-Protection for the API.

I already tried to add the /api route to the except array in VerifyCsrfToken and removed the middleware from Kernel.php but this doesn't seem to change the fact that I still need to send the CSRF-Token.

I'm using Laravel 5.8 and use JavaScript fetch to make requests.

VerifyCsrfToken:

protected $except = [
    '/api/*'
];```

I commented out VerifyCsrfToken in the Kernel:

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        // \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
    ],

    'api' => [
        'throttle:60,1',
        'bindings',
    ],
];

Example API route:

Route::get('test', function() {
    return response()->json(['success' => 'Hello!']);
})->middleware('auth:api');

How I try to access the API:

const checkStatus = (response) => {
    console.log(response);
    if (response.ok) {
        return response;
    } else {
        const error = new Error(response.statusText);
        error.response = response;
        throw error;
    }
}

const parseJSON = res => res.text();

const Fetcher = {
    get: (ressource) => {
        return fetch(CONSTANTS.API_URL + ressource, {
            method: 'GET',
            mode: 'cors',
            headers: {
                'Accept': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                //'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
            },
            credentials: 'include'
        })
            .then(checkStatus)
            .then(parseJSON)
    },
    post: (ressource, data) => {
        return fetch(CONSTANTS.API_URL + ressource, {
            method: 'POST',
            mode: 'cors',
            headers: {
                'Accept': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                //'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
            },
            credentials: 'include',
            body: data
        })
            .then(checkStatus)
            .then(parseJSON)
    }
}
Ad

Answer

Try to isolate the problem.
Remove auth:api middleware in the route:

Route::get('api/test', function() {
    return response()->json(['success' => 'Hello!']);
});

Note the url is "api/test" and not just "test" cause you defined the $except array like this:

protected $except = [
    '/api/*'
];

Do your call without passing CSRF token.

EDITED

From laravel documentation about auth:api middleware:

Laravel includes an authentication guard that will automatically validate API tokens on incoming requests. You only need to specify the auth:api middleware on any route that requires a valid access token:

it means you have to pass API token to the routes under auth:api middleware, otherwise you get 401 error.

Ad
source: stackoverflow.com
Ad