Reputation: 1635
I am trying to learn how I can pass a csrf token (I am using Laravel) with an ajax request as my ajax url returns 500 because it hasn't been given the csrf token.
Is it less secure to use a get request? can people spoof the requests from an external site? I'm just looking for the best way to do this without any security holes really.
Here is my ajax code:
saveHousekeepingNotes();
function saveHousekeepingNotes() {
$.ajax({
url: "/ajax/save-notes",
type: "POST",
data: 'Here we have some data.',
beforeSend: function(xhr) {
$('.notes-status-holder').html('Saving...');
},
success: function(data) {
var jqObj = jQuery(data);
var d = new Date();
$('.notes-status-holder').html('autosaved ' + d.toLocaleTimeString());
setInterval(function() {
saveHousekeepingNotes();
}, 5 * 1000);
},
});
}
In my blade file:
<script>$.ajaxSetup({ headers: { 'csrftoken' : '{{ csrf_token() }}' } });</script>
In my routes:
Route::group(['middleware' => 'ajax', 'prefix' => 'ajax'], function() {
Route::any('/save-notes', 'AjaxController@saveNotes');
});
In my ajax controller:
<?php
namespace App\Http\Controllers\Admin\Admin;
use Illuminate\Http\Request;
use Cache;
use Auth;
use App\Database\Website\User\Roleplay;
class AjaxController
{
public function saveNotes()
{
if (!Auth::guest()) {
$roleplay = Roleplay::where('user_id', Auth::user()->id)->first();
$roleplay->housekeeping_notes = 'We saved it:) ' . rand(10,40);
$roleplay->save();
}
}
}
My ajax middleware just checks if $request->ajax() to verify its a ajax call. So what I am basically asking is how can I pass the csrf token securely? Does Laravel handle that? or is there a better way of doing this..
Upvotes: 1
Views: 2825
Reputation: 570
If you want to pass the csrf the way you are currently doing you have to tell htaccess to pass this header to your script and also modify it's name
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# Handle custom csrf Header
RewriteCond %{HTTP:csrftoken} .
RewriteRule .* - [E=X-XSRF-TOKEN:%{HTTP:csrftoken}]
</IfModule>
Put remember @AfikDeri solution is more portable.and cleaner
Upvotes: 0
Reputation: 2580
Just use this.
_token: '{{ csrf_token() }}'
It is because ajax request is also sending the name of the field.
Normally if you create a csrf_field
, you can find it with a name _token
, just use that here.
$.ajax({
url: "/ajax/save-notes",
type: "POST",
data: {
_token: '{{ csrf_token() }}',
// rest data here
},
beforeSend: function(xhr) {
$('.notes-status-holder').html('Saving...');
},
success: function(data) {
var jqObj = jQuery(data);
var d = new Date();
$('.notes-status-holder').html('autosaved ' + d.toLocaleTimeString());
setInterval(function() {
saveHousekeepingNotes();
}, 5 * 1000);
},
});
Upvotes: 1
Reputation: 2109
well, according to Laravel Docs you better store your csrf token in a meta tag, like so:
<meta name="csrf-token" content="{{ csrf_token() }}">
Then inside your main javascript file include this header with every request (please note that the header name you provided was wrong):
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Then it should work :)
Upvotes: 2