Laravel ajax post not working even though CSRF token included - ajax

I am having difficulty getting an ajax post to work with laravel v5.5.24. Here is what my ajax call looks like:
var CSRF_TOKEN = $('meta[name="csrf-token"]').attr('content');
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: "/postCustomer?XDEBUG_SESSION_START=19683",
type: 'POST',
data: {_token: CSRF_TOKEN, message:myData, "_method": 'POST'},
dataType: 'JSON',
success: function (data) {
console.log('call to postCustomer successful');
}
});
Here is my route:
Route::post('/postCustomer','AdminUserController#store');
The interesting thing about this problem is that when all the post's are changed to get's (both in the ajax call and in the route) the request arrives and is handled correctly. The debug is triggered, and all is well. However, iof the route and the ajax call is set to POST, the debug is never triggered, and the request does not appear to make it. Naturally this smells like a CRSF issue, but I am including the CRSF token in the header.

if the javascript code inside .blade.php file try this
data: {_token:'{{ csrf_field() }}', message:myData, "_method": 'POST'},
hope its help

Try this,
<meta name="_token" content="{!! csrf_token() !!}"/>
$.ajaxSetup({
headers:
{'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')}
});
$.ajax({
url: "/postCustomer?XDEBUG_SESSION_START=19683",
type: 'POST',
data: {message:myData, "_method": 'POST'},
dataType: 'JSON',
success: function (data) {
console.log('call to postCustomer successful');
}});
No need to pass token in ajax data again.

Heartfelt thanks to everyone who responded. A couple of things helpled in fuguring this thing out. First of all, I consolidated the CSRF token mentions,
and confined what I was sending as data to just that - no need to include the CSRF token in the data if you do it in the ajaxSetup. The second thing wasn't visible from my post, but I was encountering a race condition involving the button that triggered the ajax transaction. The button was causing a page reload before ajax could do its thing, and this is why occasionally the thing would appear to work, but mostly not. So the return false is necessary to prevent that - probably not in both places, but certainly after the ajax transaction has been invoked and we are waiting for the callback. The code which works can be found below. I hope it will prevent somebody else from spending a night going mad trying how to figure out what their POST's aren't working. Take away points: handle your CSRF in an ajaxSetup call, and return false from the whole business.
Thanks again to everybody.
-George Pipkin
Afton, Virginia
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
/* the route pointing to the post function */
url: "/postCustomer?XDEBUG_SESSION_START=19159",
type: 'POST',
/* send the csrf-token and the input to the controller */
data: {message:myData},
dataType: 'json',
/* remind that 'data' is the response of the AjaxController */
success: function (data) {
$("#success_msg").show();
return false;
}
});
return false;

You should have to pass the _token inside the data object.
data: {_token:'{{ csrf_token() }}',, message:myData, "_method": 'POST'},

Related

Ajax call with flask-seasurf

I am developing a small app on localhost and using flask-seasurf to prevent csrf attacks. All my non-ajax forms work correctly with flask-seasurf. I have one form that triggers an ajax call to '/checkajax' on form submit; this worked until I started to use flask-seasurf but now I get a console error and the ajax doesn't work:
Warning in flask_seasurf: Forbidden (CSRF token missing or incorrect): /checkajax
The form triggering the ajax call has the standard hidden field containing the 'csrf_token()' function call of flask-seasurf embedded in the jinja page template:
<input id="csrf-token" type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
The ajax call structure is:
$("#submit").submit(function(event) {
event.preventDefault();
$.ajax({
url: "/checkajax",
data: {...},
type: "POST",
datatype: "text",
success: function(response){
...
},
error: function(response) {
...
}
});
});
I can see from the site cookie that there is an entry for '_csrf_token' generated by flask-seasurf. Can anyone give some insight as to why this ajax call is now not working?
The solution to my problem was to modify the header of the ajax call to include X-CSRFToken defined as the flask-seasurf token from my form:
var csrf_token = $("csrf-token").val()
$("#submit").submit(function(event) {
event.preventDefault();
$.ajax({
headers: {"X-CSRFToken", csrf_token},
url: "/checkajax",
data: {...},
type: "POST",
datatype: "text",
success: function(response){
...
},
error: function(response) {
...
}
});
});
Hope that helps someone else.

TokenMismatchException during AJAX polling in Laravel

In my Laravel application, I have a notification system. This is run using AJAX polling techniques (i.e. a ajax post function is run every 5 seconds or so) similar to:
$.ajaxSetup({
headers: {
'X-CSRF-Token': CSRF_TOKEN
}
});
(function pollForNewNotifications() {
setTimeout(function () {
$.ajax({
type: 'POST',
url: 'http://example.com/get-notifications',
dataType: 'json',
data: {
// data that is sent
},
success: function (data) {
// add new notifications if data is not empty logic
pollForNewNotifications();
}
})
.fail(function (xhr, status, err) {
console.error(xhr.responseText)
});
}, 5000);
})();
Now this works most of the time.
However, the issue is that I sometimes find that over long period of inactivity I get a TokenMismatchException in VerifyCsrfToken.php error and automatically logged out.
I believe that this is the case because the CSRF token changes or longer is valid (I may be wrong).
How can I solve this issue?
Change the session's lifetime:
https://github.com/laravel/laravel/blob/a282304/config/session.php#L32
You can remove token check to this particular url so it can make request without checking csrf token. Go to app/Http/Middleware/VerifyCsrfToken.php
place this
protected $except = [
'get-notifications',
];

How to show AJAX response message in alert?

I am sending username and password as request parameter to the server in AJAX and trying to show the response message. But not able to showing the response message.In fiddler it is showing the response message. But while on the browser screen it is not showing.PLEASE somebody help me out where i am wrong or need to change anything..
I have written like this-
$(document).ready(function () {
$("#btnCity").click(function () {
$.ajax({
type: "POST",
url: "http://test.xyz.com/login",
crossDomain: true,
contentType: "application/json; charset=utf-8",
data: { username: "abc", password: "1234" },
dataType: "JSONP",
jsonpCallback: 'jsonCallback',
async: false,
success: function (resdata) {
alert(resdata);
},
error: function (result, status, err) {
alert(result.responseText);
alert(status.responseText);
alert(err.Message);
}
});
});
});
TL;DR: I guess the problem is on the server side of your code (that we don't know yet).
At first: I don't know why it fails for you. I've taken your code and ran it against a public available JSONP API, that returns the current IP of your system and it worked.
Please try yourself using the URL: http://ip.jsontest.com/.
So most probably, the server doesn't return the right response to the JSONP request. Have a look at the network tab in developer tools. With your current code, the answer of the server should be something like:
jsonCallback({'someResponseKeys': 'someResponseValue'});
Note: The header should contain Content-Type:application/javascript!
BTW, even if this doesn't for now solve your problem - here are some tweaks, I'd like to advice to you:
Don't set async to false, at the documentation of jQuery.ajax() says:
Cross-domain requests and dataType: "jsonp" requests do not support synchronous
operation.
You don't need to set a jsonpCallback, because jQuery will generate and handle (using the success function a random one for you. Quote from the docs:
This value will be used instead of the random name automatically generated by jQuery. It is preferable to let jQuery generate a unique name as it'll make it easier to manage the requests and provide callbacks and error handling.
So here comes my code:
$(document).ready(function () {
$("#btnCity").click(function () {
$.ajax({
type: "POST",
url: "http://ip.jsontest.com/",
crossDomain: true,
data: { username: "abc", password: "1234" },
dataType: "JSONP",
success: function (resdata) {
console.log("success", resdata);
},
error: function (result, status, err) {
console.log("error", result.responseText);
console.log("error", status.responseText);
console.log("error", err.Message);
}
});
});
});
A working example can be found here.
Another solution, like Yonatan Ayalon suggested, can be done with a predefined function and then setting the jsonpCallback explicitly to the function that should be called.
if you see the response in Fiddler, it seems that the issue is in the callback function.
you are doing a jsonP call - which means that you need a callback function to "read" the response data.
Do you have a local function that calls "jsonCallback"?
this is a simple jsonP request, which initiates the function "gotBack()" with the response data:
function gotBack(data) {
console.log(data);
}
$.ajax({
url: 'http://test.xyz.com/login' + '?callback=?',
type: "POST",
data: formData,
dataType: "jsonp",
jsonpCallback: "gotBack"
});
You can try with the following methods and close every instance of chrome browser in task manager, then open browser in web security disable mode by the command "chrome.exe --disable-web-security"
success: function (resdata) {
alert(resdata);
alert(JSON.stringify(resdata));
},
And the better option to debug the code using "debugger;"
success: function (resdata) {
debugger;
alert(resdata);
alert(JSON.stringify(resdata));
},

Linking AJAX with PHP code. Do i need to write it again?

I have a real problem. I have a php code and a form where when the form is submitted a POST request is sent and the page reloads again and ofcourse the post is viwed in the page.But i want to work with AJAX in order page not to be refreshed.I know the basics of AJAX but i don't want to build all the project from the beggining.Is there a way in success function of AJAX to link to my php code??
$.ajax({
type: "POST",
url: "index.php",
datatype: "html",
data: dataString,
success: function(data) {
//How can i link here to start running my php code which is located in the same page.
}
});
$.ajax({
type: "POST",
url: "somescript.php",
datatype: "html",
data: dataString,
success: function(data) {
// try this
console.log(data);
// see what 'data' actually is
}
});
then check in the browser by hitting F12 to look at the console.
also are you sure you want datatype of html ? you probably want a data type of json or XML , what is the server returning to you after the ajax post?
You have to cancel the form's submission so that the ajax request will take place, otherwise it is canceled. Also use .serialize to get a name-value pair string of the form data to use in the ajax call.
Html
<form id="MyForm">
<button id="MyButtonId">Submit</button>
</form>
JS
$("#MyForm").submit(function(e){
//Prevents the form from being submitted
e.preventDefault();
$.ajax({
type: "POST",
data: $("#MyForm").serialize(),
url: "somescript.php",
datatype: "html",
data: dataString,
success: function(data) {
alert(data);
}
});
});

Symfony2 Ajax app_dev.php in url

Just starting out in Symfony2 and really loving it after being a long time ZF1 developer.
Started to add some Ajax functionality to a site tonight and am a bit confused about the following.
in my ajax call eg:
$.ajax({
url: '/app_dev.php/ajax/urlgetter',
data: "url="+urlinput,
dataType: 'html',
timeout: 5000,
success: function(data, status){
// DO Stuff here
}
});
I had to add /app_dev.php to the url to make it work in dev environment. Is there not a better way of doing this? Does this mean when I change the project to a production environment I need to search and replace all instances of /app_dev.php?? Hopefully I have totally missed something simple.
I ended up using the jsrouting-bundle
Once installed I could simply do the following:
$.ajax({
url: Routing.generate('urlgetter'),
data: "url="+urlinput,
dataType: 'html',
timeout: 5000,
success: function(data, status){
// DO Stuff here
}
});
where urlgetter is a route defined in routing.yml like:
urlgetter:
pattern: /ajax/urlgetter
defaults: { _controller: MyAjaxBundle:SomeController:urlgetter }
options:
expose: true
notice the expose: true option has to be set for the route to work with jsrouting-bundle
I guess this question is already kind of old but I came across the same problem.
Its not any "best practice" solution but here is what I do.
In twig you can use this {{ path('yourRouteName') }} thing in a perfect way. So in my twig file I have a structure like that:
...
<a href="{{ path('myRoute') }}"> //results in e.g http://localhost/app_dev.php/myRoute
<div id="clickMe">Click</div>
</a>
Now if someone clicks the div, I do the following in my .js file:
$('#clickMe').on('click', function(event) {
event.preventDefault(); //prevents the default a href behaviour
var url = $(this).closest('a').attr('href');
$.ajax({
url: url,
method: 'POST',
success: function(data) {
console.log('GENIUS!');
}
});
});
I know that this is not a solution for every situation where you want to trigger an Ajax request but I just leave this here and perhaps somebody thinks it's useful :)
Since this jQuery ajax function is placed on twig side and the url points to your application you can insert routing path
$.ajax({
url: '{{ path("your_ajax_routing") }}',
data: "url="+urlinput,
dataType: 'html',
timeout: 5000,
success: function(data, status){
// DO Stuff here
}
});

Resources