Check out Laravel Airlock
Validate CSRF token on API controller for SPA
Hi everyone,
I wrote a little Vue SPA app that uses the Laravel API. Now I'd like to protect the endpoint for sending a contact form so that the data can not be posted from using Postman or other tools.
So in my JS entry point, I saw this:
/**
* We'll load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
* CSRF token as a header based on the value of the "XSRF" token cookie.
*/
window.axios = require ('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
The application.blade.php that loads the Vue-app includes
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
This is my api route:
/*Contact Routes*/
Route::group(['prefix' => 'contact'], function ($router) {
/*Send*/
Route::post('/send', 'ContactApiController@send')
->name('api.contact.send');
});
This is the middleware group config in Kernel.php
/**
* The application's route middleware groups.
*
* @var array
*/
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,
\Spatie\ResponseCache\Middlewares\CacheResponse::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
How can I add CSRF-protection to the api route in this case? Would it be enough to add \App\Http\Middleware\VerifyCsrfToken::class to the api group?
The answer is not simple, since there is many consideration to take into account.
If your API is accessed only by your SPA application then it's better to use JWT (https://jwt.io/ ) or Airlock (as written in documentation quoting "Airlock does not use tokens of any kind. Instead, Airlock uses Laravel's built-in cookie based session authentication services. This provides the benefits of CSRF protection, session authentication, as well as protects against leakage of the authentication credentials via XSS. Airlock will only attempt to authenticate using cookies when the incoming request originates from your own SPA frontend."
However if your API is accessed by third party, then they are "stateless", "as per the REST (REpresentational “State” Transfer) architecture, the server does not store any state about the client session on the server side... Session state is therefore kept entirely on the client. client is responsible for storing and handling all application state related information on client side."
Read more here https://stackoverflow.com/questions/2392100/how-to-prevent-csrf-in-a-restful-application
Shortly, if you are building an VUE SPA and need to use sessions, csrf, etc, then you can use web routes, which already include all sessions, csrf, etc. Otherwise you must include all middleware like in web, not sure exactly whichbut for sure sessions, cookies and csrf middleware.
I also use Passport a year ago for a project, but it was not best for me, and I discover it too late. Because Passport allow even machine to machine communication, while in my case, and I think also in your case, is not required. I have write here about it https://laracasts.com/discuss/channels/laravel/passport-password-grant-tokens and someone recently report this issues is reported here https://github.com/laravel/passport/issues/984
I hope this help.
Please or to participate in this conversation.