最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

php - Disable Laravel CSRF Protection for api routes when consuming API with JavaScript - Stack Overflow

programmeradmin0浏览0评论

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 mented 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)
    }
}

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 mented 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)
    }
}
Share Improve this question edited Jul 2, 2019 at 0:42 pete asked Jul 1, 2019 at 23:42 petepete 3595 silver badges15 bronze badges 8
  • If you use the $except array you do not need to apply auth:api middleware to the route. But the route url should be something like "api/test" – Giao M Commented Jul 2, 2019 at 9:27
  • Hm okay, but I still want the routes to be potected. I send the laravel_token with every request so that I can access protected routes, but apparently that's not enough because I also have to sent the CSRF token which is not what I want. – pete Commented Jul 2, 2019 at 9:36
  • Still you are telling laravel to not check for the CSRF token for "api/*" routes but your route is just "test" (it should be "api/test") – Giao M Commented Jul 2, 2019 at 9:38
  • Thanks, I just tried it, but without the X-CSRF-TOKEN in the request header, I get the error 401 unauthorized. – pete Commented Jul 2, 2019 at 9:54
  • 401 is another error and its about auth token – Giao M Commented Jul 2, 2019 at 9:55
 |  Show 3 more ments

2 Answers 2

Reset to default 2

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 ining 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.

under routes folder handle your api routes in api.php not in web.php

发布评论

评论列表(0)

  1. 暂无评论