Skip to content

Commit 89b20a8

Browse files
Iltar van der Bergxabbuh
Iltar van der Berg
authored andcommitted
[Cookbook, Security] Added user_checkers.rst
1 parent 25fe737 commit 89b20a8

File tree

2 files changed

+216
-0
lines changed

2 files changed

+216
-0
lines changed

cookbook/security/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Authentication (Identifying/Logging in the User)
2323
multiple_user_providers
2424
firewall_restriction
2525
host_restriction
26+
user_checkers
2627

2728
Authorization (Denying Access)
2829
------------------------------

cookbook/security/user_checkers.rst

+215
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
.. index::
2+
single: Security; Creating and Enabling Custom User Checkers
3+
4+
How to Create and Enable Custom User Checkers
5+
=============================================
6+
7+
During the authentication of a user, additional checks might be required to verify
8+
if the identified user is allowed to log in. By defining a custom user checker, you
9+
can define per firewall which checker should be used.
10+
11+
.. versionadded:: 2.8
12+
Defining a custom user checker was introduced in Symfony 2.8.
13+
14+
15+
Creating a Custom User Checker
16+
------------------------------
17+
18+
User checkers are defined in PHP classes that must implement the
19+
:class:`UserCheckerInterface Symfony\\Component\\Security\\Core\\UserCheckerInterface`.
20+
This interface defines two methods called ``checkPreAuth()`` and ``checkPostAuth()``
21+
to perform checks before and after user authentication. If one or more
22+
conditions are not met, an exception should be thrown which extends the
23+
:class:`AccountStatusException Symfony\\Component\\Security\\Core\\Exception\\AccountStatusException`
24+
25+
.. code-block:: php
26+
27+
namespace App\Security;
28+
29+
use Symfony\Component\Security\Core\User\UserCheckInterface;
30+
31+
class UserChecker implements UserCheckerInterface
32+
{
33+
public function checkPreAuth(UserInterface $user)
34+
{
35+
if (!$user instanceof AppUser) {
36+
return;
37+
}
38+
39+
// user is deleted, show a generic Account Not Found message.
40+
if ($user->isDeleted()) {
41+
throw new AccountDeletedException('...');
42+
}
43+
}
44+
45+
public function checkPostAuth(UserInterface $user)
46+
{
47+
if (!$user instanceof AppUser) {
48+
return;
49+
}
50+
51+
// user account is expired, the user may be notified
52+
if ($user->isExpired()) {
53+
throw new AccountExpiredException('...');
54+
}
55+
}
56+
}
57+
58+
Enabling the Custom User Checker
59+
--------------------------------
60+
61+
All that's left to be done is creating a service definition and configuring
62+
this in the firewall configuration. Configuring the service is done like any
63+
other service:
64+
65+
.. configuration-block::
66+
67+
.. code-block:: yaml
68+
69+
# app/config/services.yml
70+
services:
71+
app.user_checker:
72+
class: App\Security\UserChecker
73+
74+
.. code-block:: xml
75+
76+
<!-- app/config/services.xml -->
77+
<?xml version="1.0" encoding="UTF-8" ?>
78+
<container xmlns="http://symfony.com/schema/dic/services"
79+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
80+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
81+
82+
<services>
83+
<service id="app.user_checker" class="App\Security\UserChecker" />
84+
</services>
85+
</container>
86+
87+
.. code-block:: php
88+
89+
// app/config/services.php
90+
use Symfony\Component\DependencyInjection\Definition;
91+
92+
$userChecker = new Definition('App\Security\UserChecker');
93+
$container->setDefinition('app.user_checker', $userChecker);
94+
95+
All that's left to do is add the checker to the desired firewall where the value
96+
is the service id of your user checker:
97+
98+
.. configuration-block::
99+
100+
.. code-block:: yaml
101+
102+
# app/config/security.yml
103+
104+
# ...
105+
security:
106+
firewalls:
107+
secured_area:
108+
pattern: ^/
109+
user_checker: app.user_checker
110+
# ...
111+
112+
.. code-block:: xml
113+
114+
<!-- app/config/security.xml -->
115+
<?xml version="1.0" encoding="UTF-8"?>
116+
<srv:container xmlns="http://symfony.com/schema/dic/security"
117+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
118+
xmlns:srv="http://symfony.com/schema/dic/services"
119+
xsi:schemaLocation="http://symfony.com/schema/dic/services
120+
http://symfony.com/schema/dic/services/services-1.0.xsd">
121+
122+
<config>
123+
<!-- ... -->
124+
<firewall name="secured_area" pattern="^/">
125+
<user-checker>app.user_checker</user-checker>
126+
<!-- ... -->
127+
</firewall>
128+
</config>
129+
</srv:container>
130+
131+
.. code-block:: php
132+
133+
// app/config/security.php
134+
135+
// ...
136+
$container->loadFromExtension('security', array(
137+
'firewalls' => array(
138+
'secured_area' => array(
139+
'pattern' => '^/',
140+
'user_checker' => 'app.user_checker',
141+
// ...
142+
),
143+
),
144+
));
145+
146+
147+
Additional Configurations
148+
-------------------------
149+
150+
It's possible to have a different user checker per firewall.
151+
152+
.. configuration-block::
153+
154+
.. code-block:: yaml
155+
156+
# app/config/security.yml
157+
158+
# ...
159+
security:
160+
firewalls:
161+
admin:
162+
pattern: ^/admin
163+
user_checker: app.admin_user_checker
164+
# ...
165+
secured_area:
166+
pattern: ^/
167+
user_checker: app.user_checker
168+
169+
.. code-block:: xml
170+
171+
<!-- app/config/security.xml -->
172+
<?xml version="1.0" encoding="UTF-8"?>
173+
<srv:container xmlns="http://symfony.com/schema/dic/security"
174+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
175+
xmlns:srv="http://symfony.com/schema/dic/services"
176+
xsi:schemaLocation="http://symfony.com/schema/dic/services
177+
http://symfony.com/schema/dic/services/services-1.0.xsd">
178+
179+
<config>
180+
<!-- ... -->
181+
<firewall name="admin" pattern="^/admin">
182+
<user-checker>app.admin_user_checker</user-checker>
183+
<!-- ... -->
184+
</firewall>
185+
<firewall name="secured_area" pattern="^/">
186+
<user-checker>app.user_checker</user-checker>
187+
<!-- ... -->
188+
</firewall>
189+
</config>
190+
</srv:container>
191+
192+
.. code-block:: php
193+
194+
// app/config/security.php
195+
196+
// ...
197+
$container->loadFromExtension('security', array(
198+
'firewalls' => array(
199+
'admin' => array(
200+
'pattern' => '^/admin',
201+
'user_checkers' => 'app.admin_user_checker'
202+
// ...
203+
),
204+
'secured_area' => array(
205+
'pattern' => '^/',
206+
'user_checker' => 'app.user_checker',
207+
// ...
208+
),
209+
),
210+
));
211+
212+
.. note::
213+
214+
Internally the user checkers are aliased per firewall. For `secured_area` the alias
215+
`security.user_checker.secured_area` would point to `app.user_checker`.

0 commit comments

Comments
 (0)