sometimes we need authenticate a user on symfony with other field or property after the password verification, for example, a field or column with name verificated or expired ( in case that the column is a DateTime ).
we can use The Security Events and the flow is how follow:
We have 5 types of Events that are triggered when the user put the password in the input field and push the submit button. The events are:
- CheckPassportEvent
- AuthenticationTokenCreatedEvent
- AuthenticationSuccessEvent
- LoginSuccessEvent
- LoginFailureEvent
The first event, CheckPassportEvent, allow see the information of User Object before the auth, and we can, in this case, throw an exception.
Even better, Symfony have a cool tool called , UserChecker, that implement the UserCheckerInterface interface and you can access to the User Object before the auth.
For example:
namespace App\Security;
use App\Entity\User as AppUser;
use Symfony\Component\Security\Core\Exception\AccountExpiredException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAccountStatusException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class UserChecker implements UserCheckerInterface
{
public function checkPreAuth(UserInterface $user): void
{
if (!$user instanceof AppUser) {
return;
}
if ($user->isDeleted()) {
// the message passed to this exception is meant to be displayed to the user
throw new CustomUserMessageAccountStatusException('Your user account no longer exists.');
}
}
public function checkPostAuth(UserInterface $user): void
{
if (!$user instanceof AppUser) {
return;
}
// user account is expired, the user may be notified
if ($user->isExpired()) {
throw new AccountExpiredException('...');
}
}
}
The interface have two methods, checkPreAuth and checkPostAuth, and allow catch, the information of User Entity before the access token is created. A good place for put our conditions.
In this example, we can throw an exception, if the user is deleted or the user is not verified yet ( when we send a email to user for activate an user's account ) :
if ($user->isDeleted()) {
// the message passed to this exception is meant to be displayed to the user
throw new CustomUserMessageAccountStatusException('Your user account no longer exists.');
}
and show the exception on a Twig template:
{% if error %}
<div class="alert alert-danger">
{{ error.messageKey|trans(error.messageData, 'security') }}
</div>
{% endif %}
Oldest comments (1)
Great article!