I'm trying to get a header value with:
Request::header('csrf_token')
though, my firebug says in the headers that I have the csrf_token set to baMDpF0yrfRerkdihFack1Sa9cchUk8qBzm0hK0C. In fact, I can get that csrf_token instead with a native php code:
getallheaders()['csrf_token']
Now the question is am I doing my XSRF-protection right? or maybe there is a flaw in that php code I did, that I really have to use buggy laravel 4 function
Request::header('csrf_token')
which returns nothing but blank. And I just missed something. maybe in my Laravel 4 configurations, etc?
P.S: I am using AngularJS, but maybe it does not matter what clientside I use. I have this link as my guide: How to send csrf_token() inside AngularJS form using Laravel API?
I solved the problem by removing the underscore '_' in csrf_token so it would be crsftoken instead.
Request::header('csrf_token'); // Not working
Request::header('csrftoken'); // Working!
I think the problem there is that in the following answer at How to send csrf_token() inside AngularJS form using Laravel that you used, the csrf_token is not sent in the header of your XMLHttpRequest but in the form it self.
You need then to filter it in your laravel backend as a regular Input field. See below for a working example :
Route::filter('csrf_json', function()
{
if (Session::token() != Input::get('csrf_token'))
{
throw new Illuminate\Session\TokenMismatchException;
}
});
UPDATE
If you want to use headers in Angular, you would rather write something like :
$httpProvider.defaults.headers.common['Authorization'] = TOKEN;
In order to aplly a new header to your XMLHttpRequests. Then it is easily catchable even with raw php such as :
$aHeaders = getallheaders();
if (Session::token() != $aHeaders['authorization']) etc.
Problem
Laravel is removing headers with an underscore in the name when retrieving them with the Request::header() method. Additionally, all header names are converted to lower case in the Request::header() method.
Short Solution
On the frontend, replace all underscores in header names with dashes. csrf_token becomes csrf-token
Long Solution
Add the Laravel CSRF token as an Angular constant on your main page / layout.
<script>
angular.module("myApp").constant("CSRF_TOKEN", "<?php echo csrf_token(); ?>");
</script>
Add the token as a default header for all your requests in Angular.
angular.module("myApp").run(function($http, CSRF_TOKEN){
$http.defaults.headers.common["csrf-token"] = CSRF_TOKEN;
})
Have your csrf filter in Laravel check for a match in the headers rather than an input.
/**
* Check that our session token matches the CSRF request header token.
*
* #return json
*/
Route::filter("csrf", function() {
if (Session::token() !== Request::header("csrf-token")) {
return Response::json(array(
"error" => array(
"code" => "403",
"message" => "Ah ah ah, you didn't say the magic word.",
),
));
}
}
Request::header() is indeed used for the retrieval of headers, but check where the token is being set.. the CSRF token should be placed into the session by Laravel, and then it can be accessed through the Session::token() method.
If you look at the HTML generated through calls to the Form:: class, you'll see a hidden element called _token, which should then be compared to the token in the session. You can access that using Input::get('_token'), as with any other incoming GET or POST variable.
...However, all this shouldn't really be necessary, as it can be managed easily through the pre-defined CSRF filter in filters.php, just add that filter to the desired route or route group and you'll be protected, without having to get into the details of it.
the problem is with the Symfony Request object, which is extended in the Laravel framework. See this github thread
https://github.com/laravel/framework/issues/1655#issuecomment-20595277
The solution in your case would be to set the header name to HTTP_CSRF_TOKEN or HTTP_X_CSRF_TOKEN if you like prefixing X to your custom http headers.
Related
I am using Laravel to create a RESTFUL application and I test the application with Postman. Currently, there is an issue for PATCH or PUT if the data sent from Postman with form-data.
// Parameter `{testimonial}` will be sent to backend.
Route::post ('testimonials/{testimonial}', 'TestimonialController#update');
// Parameter `{testimonial}` will not be sent to backend (`$request->all()` will be empty) if sent from Postman with form-data.
Route::patch ('testimonials/{testimonial}', 'TestimonialController#update');
Route::put ('testimonials/{testimonial}', 'TestimonialController#update');
Using form-data, $request->all() will be okay for POST.
Using x-www-form-urlencoded, $request->all() will be okay for PATCH, PUT, and POST.
However, if I am sending PUT and PATCH with form-data from Postman, the $request->all() will be empty (the parameters will not be sent to backend).
Right now the solution is to use POST for updating a model. I want to know why PATCH and PUT is not working when sent with form-data from Postman.
This is a known issue and the workaround suggestion as per the following Github comment is that when sending a PATCH / PUT requests you should do the following:
You should send POST and set _method to PUT (same as sending forms) to make your files visible
So essentially you send a POST request with a parameter which sets the actual method and Laravel seems to understand that.
As per the documentation:
Since HTML forms can't make PUT, PATCH, or DELETE requests, you will need to add a hidden _method field to spoof these HTTP verbs. The #method Blade directive can create this field for you:
<form action="/foo/bar" method="POST">
#method('PUT')
...
</form>
Alternatively, you can use the method_field helper function to do the above:
The method_field function generates an HTML hidden input field containing the spoofed value of the form's HTTP verb. For example, using Blade syntax:
<form method="POST">
{{ method_field('PUT') }}
</form>
I learnt how to solve it here on this post and I'd like to share what did I do.
The following image is how I setup the Postman to send a HTTP POST request and go into PUT Request and make it receive my files.
I'm not sure whether it is the right way to do a RESTFul API. But it works fine
so as everyone mentioned above and explained everything, but still i dont see the answer for cases when using a REST API so i fallowed #Caique Andrade answer and send a POST request and formed my URL link like this:
url = 'https://yourwebsite.com/api/v1/users/$id?_method=PUT';
$id is the variable id for the user.
?_method=PUT is added to the url POST request to spoof the request and it works
in my case i used Dart in flutter and sent a post request using Http package Laravel catches that POST request as a PUT request
Laravel PATCH and PUT method does not work with form-data, it's known issue of Symfony and even PHP (Google for that - Laravel use many Symfony foundation packages, include Request).
If you do not need to pass file(s) via request, change form-data to raw with json content-type. E.g: {"name":"changed"}. It will be read as php://input and your code should work well ($request->all() is now ["name" => "changed]).
If you need to pass file(s), in my opinion, DO NOT pass it within the REST API methods. You can write another method to do whatever you need with your file(s) (E.g: POST form-data -> upload file -> update db -> return a file path/url/even its base64 content), then you can use its output/result to continue with your patch/put method (raw with json content-type). I always do that when I work with files in API.
Hope this help!
InertiaJS Solution
I had the same problem. When no file was send, everything works perfectly, but when i send a file, none of the fields make it to the backend.
It seems that it's a PHP limitation, receiving no file via put, as said here before.
So, for those using InertiaJS, you need to make a post - instead of a put - call and add _method: "put" to your inertia form, like this:
updateForm: this.$inertia.form({
_method: "put",
"other fields"
}),
Your controller will understand it like a PUT call, but with the file accessible to the backend.
Source:
https://inertiajs.com/manual-visits#method
I hope it is not too late, or if someone is seeking help with the FormData interface of JavaScript. Here is the solution,
In Laravel, you can use #script47 answers above, for normal Ajax request you can append the data like this, (PS: I'm using same form for Add and Update so here is my code)
let _url = '';
let _type = 'POST';
let _formData = new FormData(this);
if(user_id == '' || user_id == null){
_url = "{{ route('users.store') }}";
}else{
_url = "{{ route('users.update', ':id') }}";
_url = _url.replace(':id', user_id);
_formData.append('_method', 'PUT');
// _type = 'PUT';
}
As mentioned, this isn't a symfony (or laravel, or any other framework) issue, it's a limitation of PHP.
After trawling through a good few RFCs for php core, the core development team seem somewhat resistant to implementing anything to do with modernising the handling of HTTP requests. The issue was first reported in 2011, it doesn't look any closer to having a native solution.
That said, I managed to find this PECL extension. I'm not really very familiar with pecl, and couldn't seem to get it working using pear. but I'm using CentOS and Remi PHP which has a yum package.
I ran yum install php-pecl-apfd and it literally fixed the issue straight away (well I had to restart my docker containers but that was a given).
That is, request->all() and files->get() started working again with PATCH and PUT requests using multipart/form-data.
I believe there are other packages in various flavours of linux and I'm sure anybody with more knowledge of pear/pecl/general php extensions could get it running on windows or mac with no issue.
As #DazBaldwin says, this is a php limitation and can be solve installing apfd extension. On windows just download the dll file here according to your system settings and put php_apfd.dll on path-to-php/ext directory finally put extension=apfd in php.ini file.
it worked for me on windows.
The form media types do not have any semantics defined for PATCH, so it's really a bad idea to use them (see https://www.rfc-editor.org/errata/eid3169).
For PUT, the expected behaviour would be to store just the form-encoded payload (in that format). Is this really what you want here?
If You Route Method Is Patch And Use Postman For Api Request
If you want to send a file, for the controller, when using postman, you must set the sending mode to the post method and in the form-data section
key = _Method
Value = PATCH
You do not have to set the file so that you do not encounter any errors when sending the request.
You can also create a custom function in your controller to update the product then create an api route.
public function updateTestimonial($id, Request $request) {
$testimonial = Testimonial::where('id', '=', $id)->first();
//update logic
}
Api route
Route::post('updatetestimonial/{id}', 'Testimonial#updateTestimonial');
Use a post request and pass testimonial id.
submitForm() {
let data = new FormData();
data.append('id', this.testtimonial.id);
data.append('description', this.testtimonial.description);
axios.post("/api/updatetestimonial/" + this.testimonial.id , data, {
headers: {
'accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.8',
'Content-Type': 'multipart/form-data',
}
}).then(({ data }) => {
console.log("success");
});
},
I know this article is old.
But unfortunately, PHP still does not pay attention to form-data other than the Post method.
But you can use the library I wrote for this purpose:
composer require alireaza/php-form-data
You can also use composer require alireaza/laravel-form-data in Laravel.
You can use post method.
const form = new
just append form.append('_method', 'PATCH');
I am using Laravel to create a RESTFUL application and I test the application with Postman. Currently, there is an issue for PATCH or PUT if the data sent from Postman with form-data.
// Parameter `{testimonial}` will be sent to backend.
Route::post ('testimonials/{testimonial}', 'TestimonialController#update');
// Parameter `{testimonial}` will not be sent to backend (`$request->all()` will be empty) if sent from Postman with form-data.
Route::patch ('testimonials/{testimonial}', 'TestimonialController#update');
Route::put ('testimonials/{testimonial}', 'TestimonialController#update');
Using form-data, $request->all() will be okay for POST.
Using x-www-form-urlencoded, $request->all() will be okay for PATCH, PUT, and POST.
However, if I am sending PUT and PATCH with form-data from Postman, the $request->all() will be empty (the parameters will not be sent to backend).
Right now the solution is to use POST for updating a model. I want to know why PATCH and PUT is not working when sent with form-data from Postman.
This is a known issue and the workaround suggestion as per the following Github comment is that when sending a PATCH / PUT requests you should do the following:
You should send POST and set _method to PUT (same as sending forms) to make your files visible
So essentially you send a POST request with a parameter which sets the actual method and Laravel seems to understand that.
As per the documentation:
Since HTML forms can't make PUT, PATCH, or DELETE requests, you will need to add a hidden _method field to spoof these HTTP verbs. The #method Blade directive can create this field for you:
<form action="/foo/bar" method="POST">
#method('PUT')
...
</form>
Alternatively, you can use the method_field helper function to do the above:
The method_field function generates an HTML hidden input field containing the spoofed value of the form's HTTP verb. For example, using Blade syntax:
<form method="POST">
{{ method_field('PUT') }}
</form>
I learnt how to solve it here on this post and I'd like to share what did I do.
The following image is how I setup the Postman to send a HTTP POST request and go into PUT Request and make it receive my files.
I'm not sure whether it is the right way to do a RESTFul API. But it works fine
so as everyone mentioned above and explained everything, but still i dont see the answer for cases when using a REST API so i fallowed #Caique Andrade answer and send a POST request and formed my URL link like this:
url = 'https://yourwebsite.com/api/v1/users/$id?_method=PUT';
$id is the variable id for the user.
?_method=PUT is added to the url POST request to spoof the request and it works
in my case i used Dart in flutter and sent a post request using Http package Laravel catches that POST request as a PUT request
Laravel PATCH and PUT method does not work with form-data, it's known issue of Symfony and even PHP (Google for that - Laravel use many Symfony foundation packages, include Request).
If you do not need to pass file(s) via request, change form-data to raw with json content-type. E.g: {"name":"changed"}. It will be read as php://input and your code should work well ($request->all() is now ["name" => "changed]).
If you need to pass file(s), in my opinion, DO NOT pass it within the REST API methods. You can write another method to do whatever you need with your file(s) (E.g: POST form-data -> upload file -> update db -> return a file path/url/even its base64 content), then you can use its output/result to continue with your patch/put method (raw with json content-type). I always do that when I work with files in API.
Hope this help!
InertiaJS Solution
I had the same problem. When no file was send, everything works perfectly, but when i send a file, none of the fields make it to the backend.
It seems that it's a PHP limitation, receiving no file via put, as said here before.
So, for those using InertiaJS, you need to make a post - instead of a put - call and add _method: "put" to your inertia form, like this:
updateForm: this.$inertia.form({
_method: "put",
"other fields"
}),
Your controller will understand it like a PUT call, but with the file accessible to the backend.
Source:
https://inertiajs.com/manual-visits#method
I hope it is not too late, or if someone is seeking help with the FormData interface of JavaScript. Here is the solution,
In Laravel, you can use #script47 answers above, for normal Ajax request you can append the data like this, (PS: I'm using same form for Add and Update so here is my code)
let _url = '';
let _type = 'POST';
let _formData = new FormData(this);
if(user_id == '' || user_id == null){
_url = "{{ route('users.store') }}";
}else{
_url = "{{ route('users.update', ':id') }}";
_url = _url.replace(':id', user_id);
_formData.append('_method', 'PUT');
// _type = 'PUT';
}
As mentioned, this isn't a symfony (or laravel, or any other framework) issue, it's a limitation of PHP.
After trawling through a good few RFCs for php core, the core development team seem somewhat resistant to implementing anything to do with modernising the handling of HTTP requests. The issue was first reported in 2011, it doesn't look any closer to having a native solution.
That said, I managed to find this PECL extension. I'm not really very familiar with pecl, and couldn't seem to get it working using pear. but I'm using CentOS and Remi PHP which has a yum package.
I ran yum install php-pecl-apfd and it literally fixed the issue straight away (well I had to restart my docker containers but that was a given).
That is, request->all() and files->get() started working again with PATCH and PUT requests using multipart/form-data.
I believe there are other packages in various flavours of linux and I'm sure anybody with more knowledge of pear/pecl/general php extensions could get it running on windows or mac with no issue.
As #DazBaldwin says, this is a php limitation and can be solve installing apfd extension. On windows just download the dll file here according to your system settings and put php_apfd.dll on path-to-php/ext directory finally put extension=apfd in php.ini file.
it worked for me on windows.
The form media types do not have any semantics defined for PATCH, so it's really a bad idea to use them (see https://www.rfc-editor.org/errata/eid3169).
For PUT, the expected behaviour would be to store just the form-encoded payload (in that format). Is this really what you want here?
If You Route Method Is Patch And Use Postman For Api Request
If you want to send a file, for the controller, when using postman, you must set the sending mode to the post method and in the form-data section
key = _Method
Value = PATCH
You do not have to set the file so that you do not encounter any errors when sending the request.
You can also create a custom function in your controller to update the product then create an api route.
public function updateTestimonial($id, Request $request) {
$testimonial = Testimonial::where('id', '=', $id)->first();
//update logic
}
Api route
Route::post('updatetestimonial/{id}', 'Testimonial#updateTestimonial');
Use a post request and pass testimonial id.
submitForm() {
let data = new FormData();
data.append('id', this.testtimonial.id);
data.append('description', this.testtimonial.description);
axios.post("/api/updatetestimonial/" + this.testimonial.id , data, {
headers: {
'accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.8',
'Content-Type': 'multipart/form-data',
}
}).then(({ data }) => {
console.log("success");
});
},
I know this article is old.
But unfortunately, PHP still does not pay attention to form-data other than the Post method.
But you can use the library I wrote for this purpose:
composer require alireaza/php-form-data
You can also use composer require alireaza/laravel-form-data in Laravel.
You can use post method.
const form = new
just append form.append('_method', 'PATCH');
I'm having ongoing problems with laravel 4.1 sessions and getting unexpected behaviour.
Depending on how I call the controllers method the session either works or doesn't My app makes a call to a POST route - to add items to a cart which is a session. For some reason the session does not get updated.However if I make a call to the same function with a GET request the function works as expected.
My routes.php contains these two routes:
Route::get('testAdd', array('uses' => 'ProductsController#addToCart'));
Route::post('products/addToCart', array('uses' => 'ProductsController#addToCart'));
Both point to the same method
The method is currently this (for testing):
public function addToCart() {
Session::put("addcarttest", "add to cart");
return json_encode(Session::get('addcarttest'));
}
If I call the function with the POST method (with form data) I get the expected result and the contents of the session.
However If I then check for the session (using a profiler) it does not exist. The data did not persist.
If I then call the same method using the GET route, I get the expected result but importantly the session persists.
I thought maybe the POST method deleted sessions however once it exists it stays there - if I use the GET method and the sessin exists if I then try the POST method example again the session remains in place - so the POST method doesnt delete the session.
This is driving me crazy - I've lost a lot of hours over this and can't see why.
Am I missing something over how Laravel handles POST v GET ? Why would two different methods make a difference to underlying functions?
What do I need to do to make the session work correctly with POST?
Update:
I've now tried database driver for the session and am getting the same behaviour.
I've taken my test a stage further- I created a basic form and submitted to the url and the method worked as expected. My current form data is submitted by jquery ajax and assumed they were fairly identical in behviour.
My jquery submit function is this:
$.ajax({
url: '/products/addToCart',
type: 'POST',
async: false,
})
.done(function() {
console.log("success");
})
.fail(function() {
console.log("error");
})
.always(function() {
console.log("complete");
});
return false;
I set async to false - I assume to await the server response. (doesnt work if true either).
So the problem is a subtle difference between a form submit and an ajax submit. Both methods are hitting the same route and method - one saves the session data - the other one doesnt.
How can I overcome? Jquery submit is essential to this part of the app.
Success!
I found a similar problem relating to laravel 3. For the session to persist in an ajax call I need to return the response correctly.
return json_encode($response);
This is causing the problem. It's not it appears a valid response to enable the session to persist. I changed it to:
return Response::json($response);
This enabled the session to persist!
For some reason a normal form submit or call to the method allows the first one but ajax does not.
I've seen references elsewhere about echo statements in the method affecting the session data but did not think I had any - the return I suppose must behaving similar to an echo
Happy now (till the next problem)
This is the post that triggered the solution:
http://forumsarchive.laravel.io/viewtopic.php?id=1304
i have same issues, but when returning XML Response, not JSON.
I fixed it using session save.
\Session::put('LOGADO.ID_LOJA', $id_loja.time());
\Session::save();
This fixed everything inside AJAX Calls.
This is in reference to the solution that Ray gave.
I had a very similar problem, which your solution resolved. Initially, I had the following on my Controller:
echo json_encode(array('auth' => $auth));
I changed this to:
return Response::json(array('auth' => $auth));
However, this was only part of the solution. In my javascript file, I initially had:
data = $.parseJSON(data);
Which, if I had kept the echo in the controller...would have been needed. apparently Laravel will do some magic behind the scenes when using Response::json() so that the data that is returned is already parsed. Removing that line in my javascript file made everything happy again :)
I'm having ongoing problems with laravel 4.1 sessions and getting unexpected behaviour.
Depending on how I call the controllers method the session either works or doesn't My app makes a call to a POST route - to add items to a cart which is a session. For some reason the session does not get updated.However if I make a call to the same function with a GET request the function works as expected.
My routes.php contains these two routes:
Route::get('testAdd', array('uses' => 'ProductsController#addToCart'));
Route::post('products/addToCart', array('uses' => 'ProductsController#addToCart'));
Both point to the same method
The method is currently this (for testing):
public function addToCart() {
Session::put("addcarttest", "add to cart");
return json_encode(Session::get('addcarttest'));
}
If I call the function with the POST method (with form data) I get the expected result and the contents of the session.
However If I then check for the session (using a profiler) it does not exist. The data did not persist.
If I then call the same method using the GET route, I get the expected result but importantly the session persists.
I thought maybe the POST method deleted sessions however once it exists it stays there - if I use the GET method and the sessin exists if I then try the POST method example again the session remains in place - so the POST method doesnt delete the session.
This is driving me crazy - I've lost a lot of hours over this and can't see why.
Am I missing something over how Laravel handles POST v GET ? Why would two different methods make a difference to underlying functions?
What do I need to do to make the session work correctly with POST?
Update:
I've now tried database driver for the session and am getting the same behaviour.
I've taken my test a stage further- I created a basic form and submitted to the url and the method worked as expected. My current form data is submitted by jquery ajax and assumed they were fairly identical in behviour.
My jquery submit function is this:
$.ajax({
url: '/products/addToCart',
type: 'POST',
async: false,
})
.done(function() {
console.log("success");
})
.fail(function() {
console.log("error");
})
.always(function() {
console.log("complete");
});
return false;
I set async to false - I assume to await the server response. (doesnt work if true either).
So the problem is a subtle difference between a form submit and an ajax submit. Both methods are hitting the same route and method - one saves the session data - the other one doesnt.
How can I overcome? Jquery submit is essential to this part of the app.
Success!
I found a similar problem relating to laravel 3. For the session to persist in an ajax call I need to return the response correctly.
return json_encode($response);
This is causing the problem. It's not it appears a valid response to enable the session to persist. I changed it to:
return Response::json($response);
This enabled the session to persist!
For some reason a normal form submit or call to the method allows the first one but ajax does not.
I've seen references elsewhere about echo statements in the method affecting the session data but did not think I had any - the return I suppose must behaving similar to an echo
Happy now (till the next problem)
This is the post that triggered the solution:
http://forumsarchive.laravel.io/viewtopic.php?id=1304
i have same issues, but when returning XML Response, not JSON.
I fixed it using session save.
\Session::put('LOGADO.ID_LOJA', $id_loja.time());
\Session::save();
This fixed everything inside AJAX Calls.
This is in reference to the solution that Ray gave.
I had a very similar problem, which your solution resolved. Initially, I had the following on my Controller:
echo json_encode(array('auth' => $auth));
I changed this to:
return Response::json(array('auth' => $auth));
However, this was only part of the solution. In my javascript file, I initially had:
data = $.parseJSON(data);
Which, if I had kept the echo in the controller...would have been needed. apparently Laravel will do some magic behind the scenes when using Response::json() so that the data that is returned is already parsed. Removing that line in my javascript file made everything happy again :)
I'm trying to submit a form using jquery in symfony 1.4, but CSRF attack detected error pops up each time. This is the code i use to submit the form data:
$.ajax({
type: 'post',
cache: false,
url: $('#assign-form form').attr('action'),
data: (
'activity[id]=' + $('#activity_id').val() +
'&activity[_csrf_token]=' + $('#activity__csrf_token').val() +
'&activity[assigned_to_user_id]=' + $('#activity_assigned_to_user_id').val() +
'&activity[assigned_to_group_id]=' + $('#activity_assigned_to_group_id').val()
)
});
Am i missing something?
Thanks,
Radu.
One thing to look at is whether the Form object that is validating the input is the exact same class as the the one that generated the token. By default, the class is used in the generation of the CSRF token.
If, for example, you had an instance of a subclass of a form used to generate the form html and then you posted to an action that used the ancestor form class, the validation would most likely fail by default.
It's possible to override the token creation if it turns out this is your issue.
Also, have you verified that the value of the token field actually includes a token? A console.log() may help you discover this.
Um...as I look closer at your code, another thing to look at is that you're building a query string to pass in 'data'. Have you tried passing an actual JSON-style object instead?
Usual cause is that the browser is not accepting cookies - have you checked that the cookies are being returned as expected (e.g. iehttpheaders, wireshark, tamperdata)?
Did you configure the secret in settings.yml?
C.
This little issue has driven me mad in the past.
If it's acceptable to you to disable CSRF protection for this particular form (which it often can be), you can add the following to your Form class in /lib/form/... folder:
public function configure ()
$this->disableLocalCSRFProtection();
I believe it's possible to disable CSRF for a particular instance of the form as well if you don't always wish to have it disabled, but I haven't tried this / don't have the code at hand.
Does the session cookie really received it with ajax query ? your session cookie as returned by server should be exactly the same with a plain HTTP request (for instance the first request initiating session management) and with XMLHttpRequest, otherwise you'll get trouble with CSRF.
$('#activity__csrf_token').val()
Did you mean to have a double underscore in that element id?