Symfony 3 csrf token - rest

How can I get or set the csrf_token with symfony?
here my code and I don't know how can I do with csrf_token,
$username = $request->request->get('username');
$password = $request->request->get('password');
if($request->isMethod('POST')){
$headers = array('Accept' => 'application/json');
$query = array('email' => $username, 'mdp' => $password);
$url = ' /**/ ';
$body = Unirest\Request\Body::json($query);
$response = Unirest\Request::post('$url',$headers,$body);
return new Response(json_encode($response));
}
return $this->render('AppBundle:Default:index.html.twig');
Thanks!

Symfony doesn't provide a CSRF token to every POST request by default. My recommendation would be to use Symfony Forms that give you CSRF protection out of the box. This will also make your life easier when handling form submission, adding validation rules, rendering the form, and much more.

Bartosz answer is a possibility. But if you don't want to use a Symfony form you can do in your twig template:
<input type="hidden" name="_csrf_token" value="{{ csrf_token('my_form') }}" />
In your controller:
$csrfTtoken = $request->request->get('_csrf_token');
if ($this->isCsrfTokenValid('my_form', $csrfTtoken)) {
// csrf token is valid!
}

Related

How to test Zend framework2 form which implements CSRF element?

I have created the login form using Zend/Form and it contains input elements as well as CSRF element.
<!-- sample login.phtml code snippet -->
<form method="post" action="/xyz">
<?php
echo $this->formelement($form->get('email'));
echo $this->formelement($form->get('password'));
echo $this->formelement($form->get('csrf'));
echo $this->formelement($form->get('submit'));
?>
</form>
The following testcase fails because of the validation against CSRF element.
public function testLogin()
{
//code goes here
$params = array('email' => 'example#test.com', 'password' => 'example#test.com');
$this->dispatch($url, $method, $params);
//if the given username and password is correct the login page redirected to default home page
$this->assertResponseStatusCode(302);
}
In the above testcase i set the email and password values but i don't know how to set CSRF element. How could i test the form which implements CSRF element?
This can easily be achieved with the following:
$form = new LoginForm();
$csrf = $form->get('csrf')->getValue();
$params = array('email' => 'example#test.com',
'password' => 'example#test.com',
'csrf' => $csrf
);
Unless your form needs the form manager when you are going to have to use that rather than just instantiating the class but that's pretty easy to do in a unit test as well.
UPDATE:
Another method that works:
$form = new LoginForm();
$form->prepare();
$params = new \Zend\Stdlib\Parameters(
array(
'csrf' => $_SESSION['Zend_Validator_Csrf_salt_csrf']['hash'],
'yourotherparams' => 'thingsandstuff'
);
$this->dispatch($url, $method, $params);

display thank you message when contact form submitted

Ok, so I've looked on the forum and see similar questions to this, but i'm still not getting anywhere with the code i've pilfered from various pages.
I'm using bootstrap css to display a contact form, usual fields, name email, message etc. The action="process.php" which is where I add the user into a mysql database and then email me a confirmation that someone has submitted the form. So all is well on that front, just that I want to display a simple "thank you" message once the form has been submitted, but not by redirecting to another page.
I have the following for a message:
<!-- thank you message -->
<div id="thanks" class="alert alert-success fade">
<button href="#" type="button" class="close">×</button>
<h4>Got it!</h4>
<p>Thanks. I've received your message, I'll be in touch within 24 hours. Promise.</p>
</div>
and then use this js to add the "in" to display it once submitted:
$('#send_button').click(function () {
$('#thanks').addClass('in');
});
$('.close').click(function () {
$(this).parent().removeClass('in'); // hides alert with Bootstrap CSS3 implem
});
I briefly see the thank you alert message, but then I get redirected to "process.php" and this doesnt display anything as theres no html within, just the mysql stuff and php mailer.
Another point to note, whether this is of interest, I load the contact form initially by ajax so the url is like wdr/index.php#contact
Can someone help me finish the code. I'm sure its something simple I'm missing to make this work as it should.
Any help appreciated.
Col
Using Ajax makes it easy. here is what I use for simple sends:
The js:
$('#form_id').on('submit', function(e) {
e.preventDefault(); //Prevents default submit
var form = $(this);
var post_url = form.attr('action');
var post_data = form.serialize(); //Serialized the form data for process.php
$('#loader', form).html('<img src="../img/forms/loader.gif" /> Please Wait...');
$.ajax({
type: 'POST',
url: 'process.php', // Your form script
data: post_data,
success: function(msg) {
$(form).fadeOut(500, function(){
form.html(msg).fadeIn();
});
}
});
});
The process.php:
<?php
/* Configuration */
$subject = 'Submission received'; // Set email subject line here
$mailto = 'your email address'; // Email address to send form submission to
/* END Configuration */
$firstName = $_POST['firstName'];
$lastName = $_POST['lastName'];
$email = $_POST['email'];
$companyName = $_POST['companyName'];
$phone = $_POST['phone'];
$callTime = $_POST['callTime'];
$timestamp = date("F jS Y, h:iA.", time());
// HTML for email to send submission details
$body = "
<br>
<p>The following information was submitted through the contact form on your website:</p>
<p><b>Name</b>: $firstName $lastName<br>
<b>Email</b>: $email<br>
<b>Company name</b>: $companyName<br>
<b>Phone number</b>: $phone (Please call in the <b>$callTime</b>)</p>
<p>This form was submitted on <b>$timestamp</b></p>
";
// Success Message
$success = "
<div class=\"row-fluid\">
<div class=\"span12\">
<h3>Submission successful</h3>
<p>Thank you for taking the time to contact Pacific One Lending. A representative will be in contact with you shortly. If you need immediate assistance or would like to speak to someone now, please feel free to contact us directly at <strong>(619) 890-3605</strong>.</p>
</div>
</div>
";
$headers = "From: $firstName $lastName <$email> \r\n";
$headers .= "Reply-To: $email \r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$message = "<html><body>$body</body></html>";
if (mail($mailto, $subject, $message, $headers)) {
echo "$success"; // success
} else {
echo 'Form submission failed. Please try again...'; // failure
}
?>

Data from input form to controller

To generate form I use
{{ form_rest(form) }}
It generates me a html:
<label class="required" for="findclient_client_number">Client number</label>
<input id="findclient_client_number" type="text" required="required" name="findclient[client][number]">
At controller I am trying to access data by:
$form = $this->createForm(new FindClientType(), new FindClient());
$form->bind($this->getRequest());
$clientnumber = $form->get('number')->getData();
return $this->render(
'MyDefaultBundle:Default:client.html.twig', array('clientnumber' => $clientnumber)
);
And get error:
Child "[number]" does not exist.
How to get submitted data from that field ?
Thanks for any help...
You need to bind the request to the form first. There is a Form::bind() method that will do this for you.
$form = $this->createForm(new ClientType());
if ($request->isMethod('POST')) {
$form->bind($this->get('request'));
$form->getData(); // Will return bound data
}
You can also get data directly from the request in your controller.
$this->get('request')->request->get('name')
See http://symfony.com/doc/master/book/forms.html#using-a-form-without-a-class
In addition to Ryans answer you are using an object (FindClient). So simply bind your form, get data and handle with your FindClient object to get your number.
$form = $this->createForm(new FindClientType(), new FindClient());
if ($request->isMethod('POST')) {
$form->bind($this->getRequest());
$data = $form->getData(); // Will return bound data
$clientnumber = $data->getNumber() // assuming your getter for the number
}

Authorization http header is not working at Zend Soap Client

I Used the below code to retrive the categories from the third party site using API, but unfortunately stream context is not able to requested at their API and resulting in the Internal Error.
FYI : It is used under zend framework.
$header = "Authorization: Bearer ".$accestoken."\r\n"."Content-Type:text/xml";//.'Content-Type:application/xml';
$wsdl = 'wsdl url';
$context = stream_context_create(array('http' => array('header' => $header,'method'=>'GET')));
$options = array('stream_context'=>$context,'encoding'=>'ISO-8859-1','exceptions'=>FALSE);
$params = array ('accessToken' => $accestoken);
$response = $client->getAdCategories($params);
print_r($response);
So please find the above code and provide some solution for this issue.
$httpHeaders = array(
'http'=>array(
'protocol_version' => 1.1,
'header' => "Authorization:Bearer ".$accestoken."\r\n" ,
"Connection: close"
));
$context = stream_context_create($httpHeaders);
$soapparams = array(
'stream_context' => $context,
);
$client = new SoapClient($wsdl, $soapparams);
$response = $client->getAdCategories($params);
print_r($response);
Please refer https://bugs.php.net/bug.php?id=49853
OK, I see in the title at least this is a SOAP service you are trying to work with. You should then be using something like the Zend_Soap_Client.
Looks like you have a WSDL... so,
$client = new Zend_Soap_Client("yourwsdl.wsdl");
and then make a request like
$retval = $client->method1(10);
Looking at your code I am not 100% sure what authentication approach is in use. If basic HTTP auth you can just pass username and password as options in the client's constructor.
Setting a header might look something like this:
$auth = new stdClass();
$auth->user = 'joe';
$auth->token = '12345';
$authHeader = new SoapHeader('authNamespace', 'authenticate', $auth);
$client->__setSoapHeaders(array($authHeader));
If you need more help post your WSDL.

Functional testing form with CSRF enabled in Symfony

What is the best way of creating functional tests to test forms with CSRF protection enabled in Symfony?
Currently I have to add the following code before each form submittion:
$form = new sfGuardFormSignin();
$token = $form->getCSRFToken();
$token_name = $form->getCSRFFieldName();
Then I add the $token and $token_name to form parameters like this:
call('/login', 'POST', array (
'signin' =>
array (
'username' => $username,
'password' => $password,
$token_name => $token,
)))
The option suggested in the documentation:
'_with_csrf' => true,
Doesn't work at all.
Is there more simple way to avoid adding token to each form tested manually? Or is there a way to turn off csrf checking when running tests?
The way I've described above is ok when you have to test 1-2 forms but if project contains tens unique forms it becomes a pain.
Of course, you can't use _with_csrf option if you call directly the url.
You must pass from the form page, clicking on the submit button.
Like so:
click('signin', array('signin' => array('username' => $username, 'password' => $password), array('_with_csrf' => true)))
The string 'signin' must be adapted to your form. You can also use a more label-independent string, like 'form#myform input[type="submit"]' instead of 'signin', adapting the id of your form.
As already suggested, you can disapble CSRF for login, it's really useful for forms that modifies data.
I personally don't use functional tests that extensively (probably to my own detriment), but you could always switch the CSRF protection off in your form class for testing purposes.
public function configure ()
$this->disableLocalCSRFProtection();
You can disable csrf protection for all forms just by adding additional compiler pass:
class CsrfProtectionCompilerPass implements CompilerPassInterface
{
/**
* {#inheritdoc}
*/
public function process(ContainerBuilder $container)
{
$env = $container->getParameter('kernel.environment');
if ($env == 'test') {
$container->setParameter('form.type_extension.csrf.enabled', false);
}
}
}
Or You can disable form extension completely by adding to config:
framework:
csrf_protection: false
btw, last solutions works only if You don't have explicitly set form option csrf_protection
I would turn off CSRF for testing environment.
You should get a CSRF token by showing the page including the form.
$browser->get('/login');
$dom = new DOMDocument('1.0', $browser->getResponse()->getCharset());
$dom->loadHTML($browser->getResponse()->getContent());
$domCssSelector = new sfDomCssSelector($dom);
$token = $domCssSelector->matchSingle('input[name="_csrf_token"]')->getNode()->getAttribute('value');