Identify angular js AJAX calls in ASP.NET MVC code - ajax

I am working on a sample application using ASP.NET MVC and AngularJS.
In server side code , I have written a Action filter attribute , and in that I need to check whether the request is a normal request(Browser) or AJAX request.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if ( filterContext.HttpContext.Request.IsAjaxRequest())
{
}
}
The method mentioned in the above code snippet "IsAjaxRequest()" is not returning TRUE in case of AJAX request made using $http Angular service.
I observed that the request does not have X-Requested-With header , and even adding the header did not solve the request.
Note : This is NOT CORS call.
So My question.
How does filterContext.HttpContext.Request.IsAjaxRequest() decide whether the request is AJAX or not?
I can check the request header(whether it has a particular header or not) and decide whether the request is AJAX or not. Is it the right and only approach?

It decides by looking whether X-Requested-With header exists or not.
You can add X-Request-With header manually to $http service.
Individual request
$http.get('/controller/action', {
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
For every request
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
}]);
You can see why it is missing from Angular

Related

springsecurity: using CSRF token obtained from CrossOrigin REST service to POST data

I have this REST service on domainA:
#CrossOrigin(origins={"http://domainB"})
#RequestMapping(value="/csrf", method=RequestMethod.GET)
public #ResponseBody
CsrfToken getCsrfToken(HttpServletRequest request) {
CsrfToken token = (CsrfToken)request.getAttribute(CsrfToken.class.getName());
return token;
}
Then I want to obtain CSRF token from above service (by using javascript on domainB) and add it to a <form action="http://domainA> on domainB and send this form to domainA (it is a simple form that has a submit button).
The problem is I get HTTP Status 403 – Forbidden.
As the opposite: when I manually set the _csrf value (obtained manually in the other browser tab pointing to domainA/csrf) in the <form action="http://domainA> and submit it then it works.
The difference which I noticed is that when I manually refresh browser's tab domainA/csrf then I get constantly the same value (and this value works), but when the domainA/csrf is obtained by the javascript from the domainB it is each time different and when using it - it does not work.
Can anyone help?
domainA: www.fridayweekend.com/rest/csrf
domainB: www.friwee.com/register (hit F12 and observe what call to www.fridayweekend.com/rest/csrf returns....)
As #dur said - the problem was in the JavaScript code. I used:
$.getJSON(domainA/csrf, callback)
which was ending up each time with a new session and a new CSRF token for it.
The solution was to use cors_ajax_call function except $.getJSON, defined as below:
var cors_ajax_call = function(address, callback){
$.ajax({
url: address,
context: document.body,
xhrFields: {
withCredentials: true
}
}).success(callback);
}
Thank you for your input! Hope this help someone :)

Is Ajax POST an acceptable technique for changing server state?

I am designing a new website and I am considering using AJAX post requests for better user experience. Is using AJAX POST requests for changing server state an acceptable design practice? Are their any security concerns in using AJAX POST requests? Is it recommended to restrict the server state changes to HTTP POST only?
EDIT
I am using ASP.NET MVC web framework for implementation.
Post, Put, Patch and Delete (although the last one is barely used) are all request types that traditionally alter the server state.
In order to answer your question, it is important to consider which framework you are using, as each one might have different best practices.
From a technical point of view, they all do practically the same, they only have different semantic meanings and conventions attached to them. If you were to use Post for everything, I doubt that anybody would complain
Post back is traditional way to doing things on web application where whole page re-load on form submission. In this approach most of the codes runs at sever side.
AJAX is a modern way to building web application where most of the code runs at client side for better performance and user experience. Only required data post to server instead of posting whole page.
Post back & Ajax both create HTTP request so it is not right to say one is less secure than other. In both request attacker can inject script using cross-site scripting (XSS) or CSRF (Cross-site request forgery).
AJAX calls are itself protect CSRF using “Common Origin Policy” when CORS is disabled and JSONP requests are blocked. To prevent CSRF attack one step ahead, you can implement Anti Forgery token like in MVC framework. AJAX calls can be called from web application as well as from MVC.
In MVC, #html.antiforgerytoken() can be called on form load which store one key in hidden field and other key in cookie and using ValidateAntiForgeryToken filter, we can validate that CSRF token. The form token can be a problem for AJAX requests, because an AJAX request might send JSON data, not HTML form data. One solution is to send the tokens in a custom HTTP header.
Here is sample code snippet for more details…
Sample Server side Code to generate Anti forgery token.
/// <summary>
/// Get Anti Forgery token
/// </summary>
/// <returns></returns>
public static string GetAntiXsrfToken()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
var responseCookie = new HttpCookie("__AntiXsrfToken")
{
HttpOnly = true,
Value = cookieToken
};
if (FormsAuthentication.RequireSSL && HttpContext.Current.Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
HttpContext.Current.Response.Cookies.Set(responseCookie);
return formToken;
}
Sample Server side Code to validate Anti forgery token.
/// <summary>
/// Validate Anti Forgery token coming from secure cookie & request header
/// </summary>
static void ValidateAntiXsrfToken()
{
string tokenHeader, tokenCookie;
try
{
// get header token
tokenHeader = HttpContext.Current.Request.Headers.Get("__RequestVerificationToken");
// get cookie token
var requestCookie = HttpContext.Current.Request.Cookies["__AntiXsrfToken"];
tokenCookie = requestCookie.Value;
AntiForgery.Validate(tokenCookie, tokenHeader);
}
catch
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.StatusCode = 403;
HttpContext.Current.Response.End();
}
}
Sample code to get Anti forgery token (one part) and save into hidden field
<input name="__RequestVerificationToken" type="hidden" value="<%= CommonUtils.GetAntiXsrfToken() %>" />
Sample client side code to pass one part to Anti Forgery token into request header from hidden field and another part will go automatically from client cookie if request is generated from same origin.
function CallServer(baseUrl, methodName, MethodArgument, callback) {
$.ajax({
type: "POST",
url: baseUrl + methodName,
data: MethodArgument,
contentType: "application/json; charset=utf-8",
async: false,
dataType: "json",
headers: {'__RequestVerificationToken': $("input[name='__RequestVerificationToken']").val()
},
success: function (data) {
if (callback != undefined && typeof (callback) === "function") {
callback(data.d);
}
},
error: function (data) {
if (data.status == 401 || data.status == 403)
window.location.href = "../Common/accessdenied";
else if (data.status == 419) {
displayUserMessage(commonMessage.RE_SESSIONINFO_NOT_FOUND, true);
window.location.href = "../Common/logout";
}
else
displayUserMessage(commonMessage.SERVICE_NOT_RESPONDING, true);
}
});
}
Finally, Call ValidateAntiXsrfToken() function before processing the each AJAX request at server side.
You can find more details here…
Which one is better? Ajax post or page post[Controller httppost] when only one form is there in a page?
http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet

Angular 2 HTTP post to Web API without [FromBody]

I have a sample Angular 2 code below.
this.headers = new Headers({ 'Content-Type': 'application/json' });
this.options = new RequestOptions({ headers: this.headers });
this.http.post('/api/todo/create', JSON.stringify(todo), this.options);
I also have an API action as seen below (ASP.NET Core)
[HttpPost]
[Route("create")]
public IActionResult Create([FromBody] Todo todo)
{
return this.Ok();
}
This code works but I am not comfortable in seeing the [FromBody] attribute in the parameter. I know that for Post requests, MVC reads it from the body. But, I have been using Restangular in AngularJS before and the parameter object is sent to an API without the [FromBody] attribute.
Is there a way to just pass the object to the API action without using the [FromBody] attribute or reading the content of the request and then deserializing it to an object?
I think using the payload of a POST method is what you should do to send data to the server. You can choose the content type you want (JSON, url encoded form, ...).
That said, the Angular2 HTTP support is low-level. I mean there is no high-level API for REST. You need to set headers by your own, choose the HTTP method you want to use... I won't find something like Restangular in Angular2.
This link could help you:
https://www.quora.com/What-are-some-of-the-best-practices-for-designing-a-RESTful-API

Session Expire Symfony 2 Ajax

My application uses ajax to request data. I'm using Symfony2, and when the session expires and I make a request with ajax, the login form is shown inside the main area on my application, and not as another view as should be. How can solve this problem. Thanks
I would suggest creating event listener which will be listening for every request:
services.yml:
your_request_listener:
class: Acme\AppBundle\EventListener\RequestListener
arguments: [#security.token_storage]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onRequest }
In this event listener I would check for type of request so this would be only Ajax request listener. When request is ajax type then I would check if session has expired - if so, I would create response which will be valid response for ajax request (i.e. JsonResponse) and set this response to be sent to user.
class RequestListener
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function onRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$request->isXmlHttpRequest()) {
return; //we dismiss requests other than ajax
}
//now you check if user is authenticated/session expired/whatever you need
$token = $this->tokenStorage->getToken();
if ($token === null) {
//now you create response which you would expect in your js doing ajax, for example JsonResponse
$response = new JsonResponse(); //you should give some content here
$event->setResponse($response); //now you override response which will be sent to user
}
}
}
You could use an entry point in which you verify if the request is an AJAX request. If yes, you return a JSON response with 401 HTTP status code. Then in JS code you verify the HTTP status code. If 401, then redirect to login page.
You can read my post here with the complete solution (see my own answer to my own question). This solution is based on this excellent post.

Debugging Ajax requests in a Symfony environment

Not sure if SFDebug is any help in this situation. I am making an ajax post using jQuery. Which retrieves JSON data in my action URL and then makes a call to the Model method that executes the action. The part until my action URL, and the jQuery call to it work fine. With the data transmitted from the client to the server well received and no errors being made.
It is the part where it calls the method on the Model that is failing. My jQuery method looks like this:
$.post(url, jsonData, function(servermsg) { console.log(servermsg); }) ;
My server action is like this
public function executeMyAjaxRequest(sfWebRequest $request)
{
if($request->isXmlHttpRequest())
{
// process whatever
$servermsg = Doctrine_Core::getTable('table')->addDataToTable($dataArray);
return $this->renderText($servermsg);
}
return false;
}
The method of concern in the Table.class.php file looks like this:
public function addDataToTable($dataArray)
{
// process $dataArray and retrieve the necessary data
$data = new Data();
$data->field = $dataArray['field'];
.
.
.
$data->save();
return $data->id ;
}
The method fails up here in the model, when renderText in the action is returned and logged into the console, it returns the HTMl for SFDEBUG. Which indicates that it failed.
If this was not an Ajax call, I could debug it by seeing what the model method spat out, but this is a little tedious with Ajax in the mix.
Not looking for exact answers here, but more on how I can approach debugging ajax requests in a symfony environment, so if there are suggestions on how I can debug this, that would be great.
You must send cookie with session ide key via ajax
(Assuming you have XDEBUG configured on the server)
In order to trigger a debug session by an AJAX request you have to somehow make that request to send additional URL parameter XDEBUG_SESSION_START=1. For your example:
$.post(url + '?XDEBUG_SESSION_START=1', jsonData, function(servermsg) { console.log(servermsg); }) ;
You can also trigger it via cookie, but appending URL parameter usually easier.

Resources