Skip to content

Commit b23833d

Browse files
committed
Merge pull request #55 from naucon/csrf_token
extend security extension by csrf token manager and csrf token modifier
2 parents 3d313dc + 61f2050 commit b23833d

3 files changed

Lines changed: 78 additions & 1 deletion

File tree

Extension/SecurityExtension.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@
2828
namespace NoiseLabs\Bundle\SmartyBundle\Extension;
2929

3030
use NoiseLabs\Bundle\SmartyBundle\Extension\Plugin\ModifierPlugin;
31+
use NoiseLabs\Bundle\SmartyBundle\Exception\RuntimeException;
3132
use Symfony\Component\Security\Acl\Voter\FieldVote;
3233
use Symfony\Component\Security\Core\SecurityContextInterface;
34+
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
35+
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
3336

3437
/**
3538
* SecurityExtension exposes security context features.
@@ -39,15 +42,18 @@
3942
class SecurityExtension extends AbstractExtension
4043
{
4144
protected $context;
45+
protected $csrfTokenManager;
4246

4347
/**
4448
* Constructor.
4549
*
4650
* @param SecurityContextInterface $context A SecurityContext instance
51+
* @param CsrfTokenManagerInterface
4752
*/
48-
public function __construct(SecurityContextInterface $context = null)
53+
public function __construct(SecurityContextInterface $context = null, $csrfTokenManager = null)
4954
{
5055
$this->context = $context;
56+
$this->csrfTokenManager = $csrfTokenManager;
5157
}
5258

5359
/**
@@ -57,6 +63,7 @@ public function getPlugins()
5763
{
5864
return array(
5965
new ModifierPlugin('is_granted', $this, 'isGranted'),
66+
new ModifierPlugin('csrf_token', $this, 'getCsrfToken'),
6067
);
6168
}
6269

@@ -73,6 +80,24 @@ public function isGranted($role, $object = null, $field = null)
7380
return $this->context->isGranted($role, $object);
7481
}
7582

83+
public function getCsrfToken($tokenId)
84+
{
85+
if ($this->csrfTokenManager instanceof CsrfProviderInterface) {
86+
$tokenValue = $this->csrfTokenManager->generateCsrfToken($tokenId);
87+
}
88+
elseif ($this->csrfTokenManager instanceof CsrfTokenManagerInterface) {
89+
$tokenValue = $this->csrfTokenManager->getToken($tokenId)->getValue();
90+
} else {
91+
$this->csrfTokenManager = null;
92+
}
93+
94+
if (null === $this->csrfTokenManager) {
95+
throw new RuntimeException('CSRF tokens can only be generated if a CsrfProviderInterface or CsrfTokenManagerInterface is injected in SecurityExtension::__construct().');
96+
}
97+
98+
return $tokenValue;
99+
}
100+
76101
/**
77102
* Returns the name of the extension.
78103
*

Resources/config/smarty.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
<service id="smarty.extension.security" class="%smarty.extension.security.class%" public="false">
6262
<tag name="smarty.extension" />
6363
<argument type="service" id="security.context" on-invalid="ignore" />
64+
<argument type="service" id="form.csrf_provider" on-invalid="null" />
65+
<!--<argument type="service" id="security.csrf.token_manager" on-invalid="ignore" />-->
6466
</service>
6567

6668
<service id="smarty.extension.expression" class="%smarty.extension.expression.class%" public="false">

Tests/Extension/SecurityExtensionTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,38 @@ public function getIsGrantedTests()
8383
);
8484
}
8585

86+
public function testCsrfTokenWithCsrfTokenManager()
87+
{
88+
$tokenId = 'foo';
89+
$tokenValue = 'xsrf';
90+
$content = "{'$tokenId'|csrf_token}";
91+
$template = 'csrf_token_manager_test.html.tpl';
92+
93+
// symfony 2.3+
94+
$this->engine->setTemplate($template, $content);
95+
$context = $this->createSecurityContext();
96+
$csrfTokenManager = $this->createCsrfTokenManager($tokenId, $tokenValue);
97+
$this->engine->addExtension(new SecurityExtension($context, $csrfTokenManager));
98+
99+
$this->assertEquals($tokenValue, $this->engine->render($template));
100+
}
101+
102+
public function testCsrfTokenWithCsrfProvider()
103+
{
104+
$tokenId = 'bar';
105+
$tokenValue = 'xsrf';
106+
$content = "{'$tokenId'|csrf_token}";
107+
$template = 'csrf_provider_test.html.tpl';
108+
109+
// symfony 2.1
110+
$this->engine->setTemplate($template, $content);
111+
$context = $this->createSecurityContext();
112+
$csrfProvider = $this->createCsrfProvider($tokenId, $tokenValue);
113+
$this->engine->addExtension(new SecurityExtension($context, $csrfProvider));
114+
115+
$this->assertEquals($tokenValue, $this->engine->render($template));
116+
}
117+
86118
protected function createSecurityContext($granted = false)
87119
{
88120
$authManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
@@ -99,4 +131,22 @@ protected function createSecurityContext($granted = false)
99131

100132
return $context;
101133
}
134+
135+
protected function createCsrfTokenManager($tokenId, $value)
136+
{
137+
$csrfToken = $this->getMock('stdClass', array('getValue'));
138+
$csrfToken->expects($this->any())->method('getValue')->will($this->returnValue($value));
139+
$csrfTokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface', array('getToken', 'refreshToken', 'removeToken', 'isTokenValid'));
140+
$csrfTokenManager->expects($this->any())->method('getToken')->will($this->returnValue($csrfToken));
141+
142+
return $csrfTokenManager;
143+
}
144+
145+
protected function createCsrfProvider($tokenId, $value)
146+
{
147+
$csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface', array('generateCsrfToken'));
148+
$csrfProvider->expects($this->any())->method('generateCsrfToken')->will($this->returnValue($value));
149+
150+
return $csrfProvider;
151+
}
102152
}

0 commit comments

Comments
 (0)