Protecting a Phalcon + AngularJS Web Application Against CSRF Attacks
Hello to all! Not so long ago I ran into the problem of protecting a web application written in the Phalcon PHP Framework along with AngularJS. The problem was that there are several forms on the page that send AJAX requests to the server. How to make friends of two frameworks on security issues, I did not find a centralized solution, I had to assemble it in pieces from different sources. And in this article I would like to offer everyone who has encountered, or will encounter such a problem, a ready-made working solution.
Unfortunately, I don’t remember the source now, but I have noticed more than once that between the tags often meta tokens lay on large sites. If you look at the Phalcon documentation , you will see that the generation of the token happens in the form. This is how the token in the form is generated by default:
And what if two forms? There was a solution on the forum, but it was using a third-party library, which in my case was not a good solution, so after searching a little more on the forum, I found a solution to generate a token in the meta tag.
After reading the AngularJS documentation on working with tokens, it is proposed to transfer a token in the header with the name X-XSRF-TOKEN, but alas, in Phalcon, you had to write a separate library to process such tokens. I don’t have time for this, I'm lazy, so I had to find another more simple solution.
In addition to simplicity, it is also flexible, because absolutely all AJAX requests sent using the $ http function are protected by a token that Phalcon easily and conveniently accepts by standard means.
1. If a person wants to see the source code of the page (not through firebug, but in a separate window), then when loading from, a new token is generated, and returning to the page, no request will be processed. Perhaps this is good, there is nothing to get into the source code.
2. If suddenly there is no favicon on the page, or else there will be an empty background-image: url (""); then the browser requesting this data will generate a new token invisibly for us. I spent two or three days finding the reason for the refusal of the token, and least of all I could suspect the block with an empty background-image: url ("");
3. And how to protect forms without AJAX, and without $ http? Very simple!
In the controller, add new scopes:
And in the view we display them in a hidden field:
Now all forms are protected, Phalcon is satisfied with the data that is familiar to him, and does not use unnecessary libraries, and Angular hooks to all $ http tokens without any problems.
I am far from a security specialist, I am not a PHP guru, I just solve problems that arise when I do what I love. I did not find the same convenient and understandable solution, which is why I wanted to share it. I use this solution in a real project until problems have been noticed. Most likely you will point out errors in the comments and I will be grateful to you. I have been working with Phalcon and AngularJS since August of this year, before that I worked with CodeIgniter and jQuery, so do not judge much for such a solution to the problem if it turned out not to be as cool as it seemed to me.
Thanks for attention. If you are interested in reading about Phalcon, sign up, I have a few more useful solutions to problems when working with it.
Generate a token in the meta tag
Unfortunately, I don’t remember the source now, but I have noticed more than once that between the tags often meta tokens lay on large sites. If you look at the Phalcon documentation , you will see that the generation of the token happens in the form. This is how the token in the form is generated by default:
And what if two forms? There was a solution on the forum, but it was using a third-party library, which in my case was not a good solution, so after searching a little more on the forum, I found a solution to generate a token in the meta tag.
We attach the token to all AJAX requests
After reading the AngularJS documentation on working with tokens, it is proposed to transfer a token in the header with the name X-XSRF-TOKEN, but alas, in Phalcon, you had to write a separate library to process such tokens. I don’t have time for this, I'm lazy, so I had to find another more simple solution.
var app = angular.module('selfmd', [], function ($httpProvider)
{
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
$httpProvider.defaults.transformRequest = [function (data) {
if (data === undefined) {
data = {};
}
var token = $('meta[name=token]');
data[token.attr('title')] = token.attr('content');
return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
}];
}
In addition to simplicity, it is also flexible, because absolutely all AJAX requests sent using the $ http function are protected by a token that Phalcon easily and conveniently accepts by standard means.
if ($this->security->checkToken())
{
//Токен верный
}
Possible problems and solutions
1. If a person wants to see the source code of the page (not through firebug, but in a separate window), then when loading from, a new token is generated, and returning to the page, no request will be processed. Perhaps this is good, there is nothing to get into the source code.
2. If suddenly there is no favicon on the page, or else there will be an empty background-image: url (""); then the browser requesting this data will generate a new token invisibly for us. I spent two or three days finding the reason for the refusal of the token, and least of all I could suspect the block with an empty background-image: url ("");
3. And how to protect forms without AJAX, and without $ http? Very simple!
In the controller, add new scopes:
var token = $('meta[name=token]');
$scope.token_id = token.attr('title');
$scope.token_val = token.attr('content');
And in the view we display them in a hidden field:
Now all forms are protected, Phalcon is satisfied with the data that is familiar to him, and does not use unnecessary libraries, and Angular hooks to all $ http tokens without any problems.
Afterword
I am far from a security specialist, I am not a PHP guru, I just solve problems that arise when I do what I love. I did not find the same convenient and understandable solution, which is why I wanted to share it. I use this solution in a real project until problems have been noticed. Most likely you will point out errors in the comments and I will be grateful to you. I have been working with Phalcon and AngularJS since August of this year, before that I worked with CodeIgniter and jQuery, so do not judge much for such a solution to the problem if it turned out not to be as cool as it seemed to me.
Thanks for attention. If you are interested in reading about Phalcon, sign up, I have a few more useful solutions to problems when working with it.