Skip to content

[Cookbook, Security] Added user_checkers.rst #5530

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cookbook/security/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Authentication (Identifying/Logging in the User)
multiple_user_providers
firewall_restriction
host_restriction
user_checkers

Authorization (Denying Access)
------------------------------
Expand Down
215 changes: 215 additions & 0 deletions cookbook/security/user_checkers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
.. index::
single: Security; Creating and Enabling Custom User Checkers

How to Create and Enable Custom User Checkers
=============================================

During the authentication of a user, additional checks might be required to verify
if the identified user is allowed to log in. By defining a custom user checker, you
can define per firewall which checker should be used.

.. versionadded:: 2.8
Defining a custom user checker was introduced in Symfony 2.8.


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double empty line here

Creating a Custom User Checker
------------------------------

User checkers are defined in PHP classes that must implement the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo, we can remove "PHP"

:class:`UserCheckerInterface Symfony\\Component\\Security\\Core\\UserCheckerInterface`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

USerCheckInterface in front should be removed, it will be automatically added. (:class:Symfony\Component\Security\Core\UserCheckerInterface``)

This interface defines two methods called ``checkPreAuth()`` and ``checkPostAuth()``
to perform checks before and after user authentication. If one or more
conditions are not met, an exception should be thrown which extends the
:class:`AccountStatusException Symfony\\Component\\Security\\Core\\Exception\\AccountStatusException`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing . to end the last sentence


.. code-block:: php

namespace App\Security;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use AppBundle


use Symfony\Component\Security\Core\User\UserCheckInterface;

class UserChecker implements UserCheckerInterface
{
public function checkPreAuth(UserInterface $user)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing use statement for UserInterface, AppUser, AccountDeletedException and AccountExpiredException

{
if (!$user instanceof AppUser) {
return;
}

// user is deleted, show a generic Account Not Found message.
if ($user->isDeleted()) {
throw new AccountDeletedException('...');
}
}

public function checkPostAuth(UserInterface $user)
{
if (!$user instanceof AppUser) {
return;
}

// user account is expired, the user may be notified
if ($user->isExpired()) {
throw new AccountExpiredException('...');
}
}
}

Enabling the Custom User Checker
--------------------------------

All that's left to be done is creating a service definition and configuring
this in the firewall configuration. Configuring the service is done like any
other service:

.. configuration-block::

.. code-block:: yaml

# app/config/services.yml
services:
app.user_checker:
class: App\Security\UserChecker

.. code-block:: xml

<!-- app/config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="app.user_checker" class="App\Security\UserChecker" />
</services>
</container>

.. code-block:: php

// app/config/services.php
use Symfony\Component\DependencyInjection\Definition;

$userChecker = new Definition('App\Security\UserChecker');
$container->setDefinition('app.user_checker', $userChecker);

All that's left to do is add the checker to the desired firewall where the value
is the service id of your user checker:

.. configuration-block::

.. code-block:: yaml

# app/config/security.yml

# ...
security:
firewalls:
secured_area:
pattern: ^/
user_checker: app.user_checker
# ...

.. code-block:: xml

<!-- app/config/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<!-- ... -->
<firewall name="secured_area" pattern="^/">
<user-checker>app.user_checker</user-checker>
<!-- ... -->
</firewall>
</config>
</srv:container>

.. code-block:: php

// app/config/security.php

// ...
$container->loadFromExtension('security', array(
'firewalls' => array(
'secured_area' => array(
'pattern' => '^/',
'user_checker' => 'app.user_checker',
// ...
),
),
));


Additional Configurations
-------------------------

It's possible to have a different user checker per firewall.

.. configuration-block::

.. code-block:: yaml

# app/config/security.yml

# ...
security:
firewalls:
admin:
pattern: ^/admin
user_checker: app.admin_user_checker
# ...
secured_area:
pattern: ^/
user_checker: app.user_checker

.. code-block:: xml

<!-- app/config/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<!-- ... -->
<firewall name="admin" pattern="^/admin">
<user-checker>app.admin_user_checker</user-checker>
<!-- ... -->
</firewall>
<firewall name="secured_area" pattern="^/">
<user-checker>app.user_checker</user-checker>
<!-- ... -->
</firewall>
</config>
</srv:container>

.. code-block:: php

// app/config/security.php

// ...
$container->loadFromExtension('security', array(
'firewalls' => array(
'admin' => array(
'pattern' => '^/admin',
'user_checkers' => 'app.admin_user_checker'
// ...
),
'secured_area' => array(
'pattern' => '^/',
'user_checker' => 'app.user_checker',
// ...
),
),
));

.. note::

Internally the user checkers are aliased per firewall. For `secured_area` the alias
`security.user_checker.secured_area` would point to `app.user_checker`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use double backticks instead of single ones (single backticks is markdown syntax)