How to call server api decorated with ValidateAntiForgeryToken using Httpclientfactory Typed clients? - asp.net

I am trying to incorporate a Edit Form page using GetAsync and PostAsync using typed httpclient. Everything works except my code doesn't call API actions with ValidateAntiForgeryToken. Most of the examples online do not address httpcontent used by httpclientfactory and instead use httpresponse. I am aware that the antiforgery token is missing on my request. How do I attach it to the request header? How do I retrieve it from the view? I want to use as less Javascript as possible. Here's a snippet of my Post request service.
Edit: For what it's worth, my api is dot net core and client is dot net core mvc.
var response = await _httpclient.PostAsync("api/edit/" + id, httpcontent);
response.EnsureSuccessStatusCode(); ```

In the MVC Edit view page, it will use a hidden file (named __RequestVerificationToken) to store the ValidateAntiForgeryToken, you can use F12 developer tools to check it.
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
After modifying the data, you could use JQuery to get the updated data, then use JQuery ajax to call the API method with the ValidateAntiForgeryToken. You can refer the sample code in my reply:
if we customize antiforgery options in Startup.ConfigureServices, such as: custom the Header Name for the RequestVerificationToken.
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN"); //configure the antiforgery service to look for the X-CSRF-TOKEN header. To prevent the cross-site request forgery.
Then, we could use the following script:
$.ajax({
type: "POST",
url: "/Survey/Create",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: { "CategoryName": $("#CategoryName").val(), "CategoryID": $("#CategoryID").val() },
success: function (response) {
alert(response);
},
failure: function (response) {
alert(response.responseText);
},
error: function (response) {
alert(response.responseText);
}
});
Besides, you can also refer Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core.

Related

Why is a .net core controller Post method not accepting the anti forgery token?

I’m trying to do a POST using an API call for a form using a reactive framework (Vue 3 in my case). I’m using .net 6.0. It is not accepting the anti forgery request token. I’m putting it in the body of the request like it is for a traditional form submit.
The call in Javascript:
var token = $('input[name="__RequestVerificationToken"]').val();
var url = '/api/ShareAllocations';
$.ajax({
type: "POST",
url: url,
data: { fa: fa, '__RequestVerificationToken': token },
success: function (result) {
console.log(result)
},
complete: function (e) { },
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.responseText);
}
});
In Fiddler, the textView of the input looks like this:
Fa= … (Json data)
__RequestVerificationToken=CfDJ8BSiPpdXlmRFvbl4LFJ0x7iHfmWBSdPblTwBjlLUq-We2oD60dKqBCYx4dUwXG5Gxprtl3lW2zzs4K8_iBf8eu0RQqOM928ANv1-16rcqizvYhUDFC5iaDo97wpqCsdFFxlmhiRaHW1zxhmEcwpYMrpZWBnzUbjGkTa-qUSs5GfuT2MwJGEWWYqyz7D95RRJVA
The API call returns a 200, but then the web page shows a 400 Bad Request.
From Fiddler:
143 200 HTTPS localhost:7164 /api/ShareAllocations
144 400 HTTPS localhost:7164 /FarmAllocation/Manage
For comparison purposes, I’m showing the body of a submit in .net core. The key value pair for the anti forgery token looks the same to me.
SENIOR_LIVING_FACILITIES.FACILITY_ID=0&SENIOR_LIVING_FACILITIES.FACILITY_NAME=n&SENIOR_LIVING_FACILITIES.ADDRESS=&SENIOR_LIVING_FACILITIES.CITY=&SENIOR_LIVING_FACILITIES.STATE=ME&SENIOR_LIVING_FACILITIES.ZIP=&SENIOR_LIVING_FACILITIES.CONTACT_NAME=&SENIOR_LIVING_FACILITIES.CONTACT_ROLE=&SENIOR_LIVING_FACILITIES.PHONE=&SENIOR_LIVING_FACILITIES.EMAIL=&__RequestVerificationToken=CfDJ8BSiPpdXlmRFvbl4LFJ0x7iHfmWBSdPblTwBjlLUq-We2oD60dKqBCYx4dUwXG5Gxprtl3lW2zzs4K8_iBf8eu0RQqOM928ANv1-16rcqizvYhUDFC5iaDo97wpqCsdFFxlmhiRaHW1zxhmEcwpYMrpZWBnzUbjGkTa-qUSs5GfuT2MwJGEWWYqyz7D95RRJVA
It turns out the post was working fine. Passing the token in the body of the message works fine. I had a side effect because of a submit button so the 400 bad request was not pertinent.

Where do ajax headers go when making a server call?

I am new to the web developer side and am trying to make sense of how AJAX headers work. We use .NET Framework MVC project with some methods on the controller that are called by our views to get some data.
Example of our view ajax call to the server:
jQuery.ajax({
type: "POST",
data: { "ElementPath": ElementPath },
dataType: "json",
headers: {
'VerificationToken': forgeryId
},
url: "" + BasePath + "/Home/GetAttributes",
});
The GetAttributes method on the server accepts a string as a parameter and returns a string of JSON objects. When I put a breakpoint on the method, the only thing I see in the string parameter is the contents of ElementPath, and nothing to do with headers. In my mind the server method would also have the contents of forgeryId. So what exactly is using the headers and how?

How to call node.js REST API from .NET

If I put the jquery code below within the script tag within a html page and drag the html page into a web browser the call to the API specified in the URL is made and I get back a response in JSON format. So this works good.
The reason I want to use .NET for calling the rest API that is made in node.js is because I want to use the unit test utility that exist in visual studio.
So when I start the unit test the call to the REST API made in node.js should be made and then I can check whatever I want in the returned json format by using the assert.AreEqual.
I have googled a lot and there is several example about
Unit Testing Controllers in ASP.NET Web API 2 but I don't want to unit test controller. I only want to call the REST API(made in node.js) when I start my unit test.
I assume to use .NET in the way I want is probably quite rare.
If it's not possible to use .NET and unit test in the way that I want here
I will use another test framework.
I hope to get some help from here.
Hope you understand what I mean.
$.ajax({
type: 'GET',
url: 'http://10.1.23.168:3000/api/v1/users/1',
dataType: 'json',
async: false,
headers: {
'Authorization': 'Basic ' + btoa('DEFAULT/user:password')
},
success: function(response) {
//your success code
console.log(response);
},
error: function (err) {
//your error code
console.log(err);
}
});
Many thanks
Basically what you need to do is to call node.js' API from your C# test code in a same way you call it using jQuery. There are several ways to do it:
Use HttpWebRequest class https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest%28v=vs.110%29.aspx
Use HttpClient class https://msdn.microsoft.com/en-us/library/system.net.http.httpclient%28v=vs.118%29.aspx It's more "RESTable" since it exposes methods to call HTTP methods like GET, PUT, POST and DELETE methods directly.
3rd party software http://restsharp.org/
Generally I recommend approach #2.
Here's the example source with all the rest of the code.
Another resource is the docs.
This code snippet should be enough to get you where you need.
using(var client = newHttpClient())
{
client.BaseAddress = newUri("http://localhost:55587/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(newMediaTypeWithQualityHeaderValue("application/json"));
//GET Method
HttpResponseMessage response = awaitclient.GetAsync("api/Department/1");
if (response.IsSuccessStatusCode)
{
Departmentdepartment = awaitresponse.Content.ReadAsAsync < Department > ();
Console.WriteLine("Id:{0}\tName:{1}", department.DepartmentId, department.DepartmentName);
Console.WriteLine("No of Employee in Department: {0}", department.Employees.Count);
}
else
{
Console.WriteLine("Internal server Error");
}
}

How does Angular know there was an error on an $http request?

How does the $http function of Angular "know" the response was an error in an ASP.NET request? I'm looking at the response headers but don't see anything that looks relevant.
I have this service in Angular:
service.getStuff = function () {
return $http({
method: 'GET',
url: './GetJsonData.aspx?RequestType=Stuff'
//That asp.net page returns json on success, but a regular
//asp.net error page on failure. I know there's better ways,
//but ignore that, that's not the question here.
});
}
and I use it like this:
$scope.reloadData = function () {
MyService.getStuff().success(function (response) {
alert("good");
})
.error(function (response) {
alert("bad");
});
};
That asp.net page is (correctly) throwing an exception on bad input and angular is (correctly) recognizing it as an error. But I can't figure out it knows there was an error. Is there some header that's it looking for? In the success case I receive json and in the failure case i receieve HTML, so as a human; but the angular code doesn't know that. So how is it recognizing this was an error?
It uses the HTTP status codes. This is standard behavior for restful clients and services.

Ajax call to ASP.NEt Web Api method. Parser error when it is done from HTTPS page

$.ajax({
url: "api/basket",
type: "GET",
dataType: "json",
error: function (request, status, error) {
alert(request.responseText);
},
success: function (data) {
Process(data);
}
});
I use ASP.NEN Web forms, .Net Framework 4.0, there is an ajax call above which I make . And when it is done from normal HTTP page it gives me data, But if I make this call being on HTTPS page it returns parserror "Unexpected token <"
What is wrong?
Your ajax request isn't returning JSON, it is returning HTML or XML. Thus, when jQuery attempts to parse the response, the first character is sees is < and it throws the parse error.
Use a debugging tool such as fiddler to see exactly what your request returns.

Resources