I am trying to implement protection in one app against CSRF.
In PHP it is relatively simple to implement. I have many questions about how to do it with Extjs.
The EXTJS books I read do not address the subject and I can not find concrete guidance on this subject - with EXTJS - on the internet.
Some questions:
Using PHP, the token is sent to the EXTJS?
Do I have to create a hidden field in every form as in PHP?
Do I have to send to the server side the token in an Ext.Ajax.requestt? How to do this?
Some very simple code as a starting point:
class Token: https://www.youtube.com/watch?v=VflbINBabc4
<?php
class Token {
public static function generate() {
$_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32));
}
public static function check($token) {
if(isset($_SESSION['token']) && $token === $_SESSION['token']){
unset($_SESSION['token']);
return true;
}
return false;
}
}
?>
Query
<?php
require('conect.php');
require_once('token.php');
$action = $_REQUEST['action'];
switch($action){
case "create":{
$records = $_POST['records'];
$data = json_decode(stripslashes($records));
if(isset($_POST['cars'], $_POST['token'])){
$cars = $data->{'cars'};
if(Token::check($_POST['token'])){
$sqlQuery = "INSERT INTO the_cars (cars) VALUES (?)";
if($statement = $con->prepare($sqlQuery)){
$statement->bind_param("s", $cars);
$statement->execute();
$success= true;
}else{
$erro = $con->error;
$success = false;
}
}else{
//error
}
echo json_encode(array(
"success" => $sucess,
'errors'=> $erro
));
$statement->close();
$conexao->close();
break;
}
}
?>
I would appreciate help to understand in detail how to implement this type of protection, using the code above as an example.
Thanks in advance.
Some useful posts:
CSRF prevention for AJAX call from extjs to Struts action
How to implement CSRFGuard in ExtJs AjaxRequest?
ExtJS Store SYNC with Spring Security ON
http://blog.gugl.org/archives/category/extjs
EDITED
One possibility I like is to send the token on every Ajax request: https://www.sencha.com/forum/showthread.php?134125
Mabe in Aplication.js. file
init: function () {
Ext.require(["Ext.util.Cookies", "Ext.Ajax"], function(){
// Add csrf token to every ajax request
var token = Ext.util.Cookies.get('csrftoken');
if(!token){
Ext.Error.raise("Missing csrftoken cookie");
} else {
Ext.Ajax.defaultHeaders = Ext.apply(Ext.Ajax.defaultHeaders || {}, {
'X-CSRFToken': token
});
}
});
}
OR from Building Applications with EXT JS video publish by PACKT, but with node in serverside
var csrfToken = Ext.query('meta[name=csrf-token]')[0].getAttribute('content');
Ext.Ajax.defaultHeaders = ('X-CSRF-Token': csrfToken);
Ext.Ajax.extraParams = {'csrf': csrfToken};
I still have doubts about how to properly relate the server side (generate the token and do the respective check) with the client side.
EDITED
I have made several attempts in the last few days to run the CSRFProtector with php and EXTJS.
From the analysis carried out I was able to verify the following with Chrome Dev Tools:
If just at de beginning of the file index I add (and not in the other php files):
include_once __DIR__ .'csrfp/libs/csrf/csrfprotector.php';
csrfProtector::init()
I get on Chrome Dev Tools:
csrfprotector.js file is loaded
In loaded php files I have » Method: POST, Status 200, Type xhr, Initiator csrfprotector.js:259
I see that the data (in JSON format) and a token are sent and Request Headers as a Cookie with the same token
In the index.php file, in addition, the following is created, as expected:
(...)
<script type="text/javascript"
src="http://my_path/csrfp/js/csrfprotector.js"></script>
<script type="text/javascript">
window.onload = function() {
csrfprotector_init();
};
</script>
</body>
</html>
No error is returned
When I add at the beginning of the php file (containing the query that will receive the data of the request, for example to create a record) the include_one and csrfProtector::init() the request is made, success is false and I get a status code 403 and the message 403 Access Forbidden by CSRFProtector!
If I add an echo 'Test 1', before csrfProtector::init (); and an echo 'Test 2' after, just first echo works. So it's not a problem in my php code but in validation with csrfprotector.
In Dev Tools you see that error 403 is triggered by mentioning the following script line: csrfprotector: 259. line 259 of that file is: return this.old_send (data);
I'm going to explore the possible incompatibility of csrfprotector with JSON.
If we were able to run the CSRFProtector with PHP and EXTJS (with JSON), it would be a solution that could make all the difference for many, as it is very easy to implement.
Example of the data format received on the server-side:
Array
(
[action] => create
[_dc] => 1505398990654
[data] => {"id_cars":"id_1","cars":"test"},
)
Content-type: application/x-www-form-urlencoded
(example in linked Sencha Fiddle) or open the issue\help to fix Protector to make it work with json. The is no other way right now... – Michal Levý