In my opinion, you need to implement the CORS mechanism or protection against CSRF in your application.
CORS
With CORS, you can define which sources are allowed to perform certain actions in your application - such as submitting a form.
(I'vetakenthe image on this link .)
For example, suppose the front end of your application is in the domain site.com and the backend is in the domain app.site.com. Before the form is actually submitted, a request of type OPTIONS
is made to the backend (what is called preflight ) in order to know if the front end can actually send that data. The backend then responds with something like:
Access-Control-Allow-Origin: http://site.com
Access-Control-Allow-Methods: GET, POST
This means that only applications hosted on the site.com domain can send requests of type POST
to the backend. Any other type of request, or requests from other sources, will receive a response with status 403 Forbidden
.
Note that CORS is respected only by more modern browsers - if you attempt to submit the form using an old browser or through the command line this mechanism will not work.
Since you are using Symfony to develop the backend, I recommend that you take a look at this bundle that makes it easy to setup CORS in your application: NelmioCorsBundle .
CSRF
An attack through CSRF, XSRF or sea-surf is characterized by the fact that the user sends malicious data to the server without his consent. These attacks can be easily avoided by requiring a cookie or a posted value valid only for that data submission or a series of submissions.
Symfony has native protection against CSRF attacks. All forms generated through the application have a hidden field whose value is a hash valid only for a given form within a given session so that malicious applications can not get that value.
If you notice the CsrfProviderInterface
class, you will notice the following methods that implement CSRF protection:
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;
/**
* Marks classes able to provide CSRF protection
*
* You can generate a CSRF token by using the method generateCsrfToken(). To
* this method you should pass a value that is unique to the page that should
* be secured against CSRF attacks. This value doesn't necessarily have to be
* secret. Implementations of this interface are responsible for adding more
* secret information.
*
* If you want to secure a form submission against CSRF attacks, you could
* supply an "intention" string. This way you make sure that the form can only
* be submitted to pages that are designed to handle the form, that is, that use
* the same intention string to validate the CSRF token with isCsrfTokenValid().
*
* @author Bernhard Schussek <[email protected]>
*/
interface CsrfProviderInterface
{
/**
* Generates a CSRF token for a page of your application.
*
* @param string $intention Some value that identifies the action intention
* (i.e. "authenticate"). Doesn't have to be a secret value.
*/
public function generateCsrfToken($intention);
/**
* Validates a CSRF token.
*
* @param string $intention The intention used when generating the CSRF token
* @param string $token The token supplied by the browser
*
* @return Boolean Whether the token supplied by the browser is correct
*/
public function isCsrfTokenValid($intention, $token);
}
The implementation of this interface shows that the token is only valid if it was previously generated:
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider;
/**
* Default implementation of CsrfProviderInterface.
*
* This provider uses the session ID returned by session_id() as well as a
* user-defined secret value to secure the CSRF token.
*
* @author Bernhard Schussek <[email protected]>
*/
class DefaultCsrfProvider implements CsrfProviderInterface
{
/**
* A secret value used for generating the CSRF token
* @var string
*/
protected $secret;
/**
* Initializes the provider with a secret value
*
* A recommended value for the secret is a generated value with at least
* 32 characters and mixed letters, digits and special characters.
*
* @param string $secret A secret value included in the CSRF token
*/
public function __construct($secret)
{
$this->secret = $secret;
}
/**
* {@inheritDoc}
*/
public function generateCsrfToken($intention)
{
return sha1($this->secret.$intention.$this->getSessionId());
}
/**
* {@inheritDoc}
*/
public function isCsrfTokenValid($intention, $token)
{
return $token === $this->generateCsrfToken($intention);
}
/**
* Returns the ID of the user session.
*
* Automatically starts the session if necessary.
*
* @return string The session ID
*/
protected function getSessionId()
{
if (version_compare(PHP_VERSION, '5.4', '>=')) {
if (PHP_SESSION_NONE === session_status()) {
session_start();
}
} elseif (!session_id()) {
session_start();
}
return session_id();
}
}