feature #40840 [Security] Add passport to AuthenticationTokenCreatedEvent (scheb)

This PR was merged into the 5.3-dev branch.

Discussion
----------

[Security] Add passport to AuthenticationTokenCreatedEvent

| Q             | A
| ------------- | ---
| Branch?       | 5.x
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| License       | MIT

This is a follow-up to my previous PR #37359, which added `AuthenticationTokenCreatedEvent` to the new authenticator-based security system to inspect the security token before it becomes effective to the security system. It **adds the passport** that was used to generate that token to the event, so that it can be inspected as well.

Reasoning:
1) It makes the event more aligned with other security events (which are also providing the passport)
2) I see valid use-cases when you'd want to look into the passport/badges to decide if you'd want to make modifications to the security token. @seldaek mentioned to me in scheb/2fa#74 that he'd like to have the ability to add a badge from his custom authenticator class, which then influences 2fa being triggered or not. Having the passport in the event would make that a straight forward task.

I would like to add this to Symfony 5.3, since @wouterj plans to stabilize the authenticator security system for that release, so I believe this is worth adding it now rather than later. The constructor change could be considered a BC break, but since authenticator system is experimental, I believe it's fair to make that change now before declaring it "stable".

Commits
-------

74196e0750 Add passport to AuthenticationTokenCreatedEvent
This commit is contained in:
Wouter de Jong 2021-04-16 21:36:14 +02:00
commit 0eebd9e5f3
3 changed files with 12 additions and 3 deletions

View File

@ -6,6 +6,7 @@ The CHANGELOG for version 5.4 and newer can be found in the security sub-package
5.3 5.3
--- ---
* Add `getPassport()` method and a second `$passport` constructor argument to `AuthenticationTokenCreatedEvent`
* The authenticator system is no longer experimental * The authenticator system is no longer experimental
* Login Link functionality is no longer experimental * Login Link functionality is no longer experimental
* Add `RememberMeConditionsListener` to check if remember me is requested and supported, and set priority of `RememberMeListener` to -63 * Add `RememberMeConditionsListener` to check if remember me is requested and supported, and set priority of `RememberMeListener` to -63

View File

@ -74,7 +74,7 @@ class AuthenticatorManager implements AuthenticatorManagerInterface, UserAuthent
$token = $authenticator->createAuthenticatedToken($passport = new SelfValidatingPassport(new UserBadge(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), function () use ($user) { return $user; }), $badges), $this->firewallName); $token = $authenticator->createAuthenticatedToken($passport = new SelfValidatingPassport(new UserBadge(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), function () use ($user) { return $user; }), $badges), $this->firewallName);
// announce the authenticated token // announce the authenticated token
$token = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($token))->getAuthenticatedToken(); $token = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($token, $passport))->getAuthenticatedToken();
// authenticate this in the system // authenticate this in the system
return $this->handleAuthenticationSuccess($token, $passport, $request, $authenticator); return $this->handleAuthenticationSuccess($token, $passport, $request, $authenticator);
@ -188,7 +188,7 @@ class AuthenticatorManager implements AuthenticatorManagerInterface, UserAuthent
$authenticatedToken = $authenticator->createAuthenticatedToken($passport, $this->firewallName); $authenticatedToken = $authenticator->createAuthenticatedToken($passport, $this->firewallName);
// announce the authenticated token // announce the authenticated token
$authenticatedToken = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($authenticatedToken))->getAuthenticatedToken(); $authenticatedToken = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($authenticatedToken, $passport))->getAuthenticatedToken();
if (true === $this->eraseCredentials) { if (true === $this->eraseCredentials) {
$authenticatedToken->eraseCredentials(); $authenticatedToken->eraseCredentials();

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Security\Http\Event; namespace Symfony\Component\Security\Http\Event;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Contracts\EventDispatcher\Event; use Symfony\Contracts\EventDispatcher\Event;
/** /**
@ -22,10 +23,12 @@ use Symfony\Contracts\EventDispatcher\Event;
class AuthenticationTokenCreatedEvent extends Event class AuthenticationTokenCreatedEvent extends Event
{ {
private $authenticatedToken; private $authenticatedToken;
private $passport;
public function __construct(TokenInterface $token) public function __construct(TokenInterface $token, PassportInterface $passport)
{ {
$this->authenticatedToken = $token; $this->authenticatedToken = $token;
$this->passport = $passport;
} }
public function getAuthenticatedToken(): TokenInterface public function getAuthenticatedToken(): TokenInterface
@ -37,4 +40,9 @@ class AuthenticationTokenCreatedEvent extends Event
{ {
$this->authenticatedToken = $authenticatedToken; $this->authenticatedToken = $authenticatedToken;
} }
public function getPassport(): PassportInterface
{
return $this->passport;
}
} }