Ajax GET for external api without CSRF checking - ajax

In my laravel 5.3 application I have enable CSRF checking globally for all ajax requests.
$.ajaxSetup({
headers: { 'X-CSRF-Token' : $('meta[name=_token]').attr('content') }
});
But I have an ajax GET request for an external api as follows.
$.ajax({
url: "https://api.xxxxxxxxxxx/v1/" +code+ "?api_key="+API_KEY,
type: "GET",
dataType: "text",
success: function (data) {
},
error: function (msg) {
}
});
I need to avoid CSRF checking here. I have tried two ways but nothing works for me. In VerifyCsrfToken.php
1st way
class VerifyCsrfToken extends BaseVerifier
{
protected $except = [
'https://api.xxxxxxxxx/v1/*'
];
}
2nd way
class VerifyCsrfToken extends BaseVerifier
{
if ( ! $request->is('https://api.xxxxxxxxx/v1/*'))
{
return parent::handle($request, $next);
}
return $next($request);
}
Please figure it out, how to solve this issue.

Finally, I figured out a way within javascript. We can delete the particular header before ajax call, then reassign the header again.
delete $.ajaxSettings.headers["X-CSRF-Token"];
$.ajax({
url: "https://api.xxxxxxxxxxx/v1/" +code+ "?api_key="+API_KEY,
type: "GET",
dataType: "text",
success: function (data) {
},
error: function (msg) {
}
});
$.ajaxSettings.headers["X-CSRF-Token"] = $('meta[name=_token]').attr('content');

You can override the ajaxSetup in that ajax call like this.
$.ajax({
url: "https://api.xxxxxxxxxxx/v1/" +code+ "?api_key="+API_KEY,
type: "GET",
dataType: "text",
headers : {},
success: function (data) {
},
error: function (msg) {
}
});
Although, you shouldn't use ajaxSetup.
The settings specified here will affect all calls to $.ajax or Ajax-based derivatives such as $.get(). This can cause undesirable behavior since other callers (for example, plugins) may be expecting the normal default settings. For that reason we strongly recommend against using this API. Instead, set the options explicitly in the call or define a simple plugin to do so. : https://api.jquery.com/jquery.ajaxsetup/

This should help
$.ajax({
type:'GET',
url:"https://api.xxxxxxxxxxx/v1/" +code+ "?api_key="+API_KEY,
data:{_token: "{{ csrf_token() }}",
},
success: function( msg ) {
}
});

Related

Razor Pages PageModel binding for GET with AJAX

I am having trouble getting binding to work with a specific set of circumstances. I am using Razor Pages with ASP.NET Core 3.1 to act like a controller for servicing AJAX calls. I have already added the anti-forgery token to the Startup.cs:
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
My AJAX calls include the anti-forgery in the calls and look like:
function getTankConfig(tankId) {
var json = { id: tankId };
$.ajax({
cache: false,
type: "GET",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
url: "/Tank/Config",
contentType: "application/json",
dataType: "json",
data: JSON.stringify(json),
success: getTankConfigSuccess
});
}
function getTankConfigSuccess(data) {
if (data !== null) {
// do stuff with data
}
}
I have tried about every combination of binding technique. Using the parameter normally, adding [FromBody], adding a public property and giving it the [BindProperty] attribute, using [BindProperty(SupportsGet = true)]. It seems like it was so simple when using a controller to do this, but I am not finding the magic for making it work with Razor Pages and PageModels.
Here is the simplified version of my PageModel class:
public class TankConfigModel : PageModel
{
public JsonResult OnGet(int id)
{
TankConfigViewModel config = new TankConfigViewModel();
config.Id = id;
return new JsonResult(config);
}
}
Any help or guidance would be greatly appreciated. Thanks.
You have to add this to your razor page
#page "{id}"
and fix ajax
$.ajax({
type: "GET",
url: "/Tank/Config/"+tankId,
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (result) {
getTankConfigSuccess(result)
},
error: function (jqXHR) {
}
});

Laravel Broadcast using pusher. ToOthers not working

$.ajaxSetup({
headers:{
'X-Socket-Id': Echo.socketId()
}
});
I also tried
var socket_id= Echo.socketId();
var CSRF_TOKEN = $('meta[name="csrf-token"]').attr('content');
$.ajax({
/* the route pointing to the post function */
url: '/event',
headers: { 'X-Socket-Id': socket_id }
type: 'POST',
/* send the csrf-token and the input to the controller */
data: {
_token: CSRF_TOKEN,
message: 'a message'
},
//dataType: 'JSON',
/* remind that 'data' is the response of the AjaxController */
success: function (data) {
$(".writeinfo").append(data.msg);
}
});
also laravel is supposed to add the x-socket-id header if im not mistaken without me doing it manually. according to this site
https://github.com/laravel/echo/blob/master/src/echo.ts
it contains this
registerjQueryAjaxSetup(): void {
if (typeof jQuery.ajax != 'undefined') {
jQuery.ajaxPrefilter((options, originalOptions, xhr) => {
if (this.socketId()) {
xhr.setRequestHeader('X-Socket-Id', this.socketId());
}
});
}
}
Also in my broadcast i made sure i used ->toOThers()
it works fine on vue its, in blade where it does not want to work, it sends to everyone on the channel. I was thinking its because im using ajax i needed to add a header with socket ID but no im not so sure.

Not getting post data in controller from ajax

I am posting my form data to A controller but when I post data I am not getting in the controller when I call print_r($_POST); its returning null array I don't know what I have missed
Please let me know what inputs you want from my side
var data2 = [];
data2['user_firstname'] = user_firstname;
data2['user_lastname'] = user_lastname;
data2['user_phone'] = user_phone;
data2['user_email'] = user_email;
data2['user_username'] = user_username;
data2['user_password'] = user_password;
console.log(data2);
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: "POST",
url: "http://localhost/shago/register/submit",
data: { 'data2': data2 },
// dataType: "text",
success: function(resultData) { console.log(resultData); }
});
controller code
public function submit()
{
print_r($_POST);
}
You can use the following
public function submit(Request $request)
{
dump($request);
}
Try adding Request as parameter on your submit function
public function submit(Request $request)
{
print_r($request);
}
Also, do you really need to pass your information as an array?
You could just create a new object and pass that as well.
var data2={
'user_firstname': user_firstname,
'user_lastname': user_lastname,
'user_phone': user_phone,
'user_email': user_email,
'user_username': user_username,
'user_password': user_password
};
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: "POST",
url: "http://localhost/shago/register/submit",
data: data2,
success: function(resultData) { console.log(resultData); }
});
You need to inject Request Class injection into submit method. This can help you:
public function submit(\Illuminate\Http\Request $request)
{
dd($request->all()); // will print all data
}
of if you don't want to inject Request then this code may helps you
public function submit()
{
dd(request()->all()); // will print all data
}
Good Luck !!!
Maybe the request was intercepted by Laravel CSRF Protection policy.In order to prove it, you should add request URL in VerifyCsrfToken middleware file, like following:
protected $except = [
'yoururl'
];
If you can get the data you expect in your controller, then I am right.
Thanks all i found error in when i am sending array data now i have modified code and its working fine
see code
$.ajax({
url: "register/submit",
type: "post",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data: {'user_firstname':user_firstname,'user_lastname':user_lastname,'user_phone':user_phone,'user_email':user_email,'user_username':user_username,'user_password':user_password},
success: function(result){
console.log(result);
}
});
}

Laravel - DELETE Ajax request

I am using Laravel 5.0. I have created a RESTful Controller. Now i wanna use the destroy function via an ajax call.
This is my JS:
$.ajax({
type: 'POST',
url: '/pv/' + data.id,
data: {_method: 'delete' },
success: function(data){
console.log(data);
}
});
And this is my destroy function:
public function destroy($id)
{
$pv = PV::find($id);
$pv->delete();
return true;
}
All i got is a 500 error.
first check your route in laravel
Route::delete('/deleteprocess', 'Controller#destroy');
in javascript
$.ajax({
url: '/deleteprocess',
type: 'POST',
data:{
'_token': $('meta[name=csrf-token]').attr("content"),
'_method': 'DELETE',
},
success: function(result) {
// Do something with the result
}});
set type : POST,
set token : _token,
set method : _method as DELETE,
That's probabily a "CSRF" Exception. If you are using Ajax Request with jQuery, add this (before your $.ajax):
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
}
});
And, in your "html" ..create a new "meta tag" with csrf-token..value:
{{ csrf_token() }}
Read more: http://laravel.com/docs/5.0/routing#csrf-protection

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));
},

Resources