From a446030acad568b838a1bca2cf21e40d86494784 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Mon, 19 Jul 2021 21:09:16 +0200 Subject: [PATCH] [Security] Deprecate `PassportInterface` --- UPGRADE-5.4.md | 23 ++++++++++ UPGRADE-6.0.md | 23 ++++++++++ .../Ldap/Security/LdapAuthenticator.php | 19 +++++++- .../AuthenticationExpiredException.php | 2 +- .../Authentication/AuthenticatorManager.php | 13 +++--- .../Authenticator/AbstractAuthenticator.php | 16 ++++++- .../AbstractPreAuthenticatedAuthenticator.php | 13 +++++- .../Authenticator/AuthenticatorInterface.php | 11 ++++- .../Authenticator/FormLoginAuthenticator.php | 14 +++++- .../Authenticator/HttpBasicAuthenticator.php | 9 +++- .../Authenticator/JsonLoginAuthenticator.php | 10 +++++ .../Passport/PassportInterface.php | 2 + .../Passport/UserPassportInterface.php | 2 + .../Authenticator/RememberMeAuthenticator.php | 11 +++++ .../Token/PostAuthenticationToken.php | 2 +- .../Component/Security/Http/CHANGELOG.md | 1 + .../Security/Http/Event/LoginSuccessEvent.php | 4 +- .../AuthenticatorManagerTest.php | 44 +++++++++++++++---- 18 files changed, 192 insertions(+), 27 deletions(-) diff --git a/UPGRADE-5.4.md b/UPGRADE-5.4.md index 98a2ae0ce1c64..af00fea8aa356 100644 --- a/UPGRADE-5.4.md +++ b/UPGRADE-5.4.md @@ -52,3 +52,26 @@ Security * Deprecate `DeauthenticatedEvent`, use `TokenDeauthenticatedEvent` instead * Deprecate `CookieClearingLogoutHandler`, `SessionLogoutHandler` and `CsrfTokenClearingLogoutHandler`. Use `CookieClearingLogoutListener`, `SessionLogoutListener` and `CsrfTokenClearingLogoutListener` instead + * Deprecate `AuthenticatorInterface::createAuthenticatedToken()`, use `AuthenticatorInterface::createToken()` instead + * Deprecate `PassportInterface` and `UserPassportInterface`, use `Passport` instead. + As such, the return type declaration of `AuthenticatorInterface::authenticate()` will change to `Passport` in 6.0 + + Before: + ```php + class MyAuthenticator implements AuthenticatorInterface + { + public function authenticate(Request $request): PassportInterface + { + } + } + ``` + + After: + ```php + class MyAuthenticator implements AuthenticatorInterface + { + public function authenticate(Request $request): Passport + { + } + } + ``` diff --git a/UPGRADE-6.0.md b/UPGRADE-6.0.md index 57f1e455fe0a7..4b5d579533d71 100644 --- a/UPGRADE-6.0.md +++ b/UPGRADE-6.0.md @@ -328,6 +328,29 @@ Security * Remove `DeauthenticatedEvent`, use `TokenDeauthenticatedEvent` instead * Remove `CookieClearingLogoutHandler`, `SessionLogoutHandler` and `CsrfTokenClearingLogoutHandler`. Use `CookieClearingLogoutListener`, `SessionLogoutListener` and `CsrfTokenClearingLogoutListener` instead + * Remove `AuthenticatorInterface::createAuthenticatedToken()`, use `AuthenticatorInterface::createToken()` instead + * Remove `PassportInterface` and `UserPassportInterface`, use `Passport` instead. + Also, the return type declaration of `AuthenticatorInterface::authenticate()` was changed to `Passport` + + Before: + ```php + class MyAuthenticator implements AuthenticatorInterface + { + public function authenticate(Request $request): PassportInterface + { + } + } + ``` + + After: + ```php + class MyAuthenticator implements AuthenticatorInterface + { + public function authenticate(Request $request): Passport + { + } + } + ``` SecurityBundle -------------- diff --git a/src/Symfony/Component/Ldap/Security/LdapAuthenticator.php b/src/Symfony/Component/Ldap/Security/LdapAuthenticator.php index 30928f62278cd..33b2335256a27 100644 --- a/src/Symfony/Component/Ldap/Security/LdapAuthenticator.php +++ b/src/Symfony/Component/Ldap/Security/LdapAuthenticator.php @@ -16,6 +16,7 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface; +use Symfony\Component\Security\Http\Authenticator\Passport\Passport; use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface; /** @@ -53,7 +54,7 @@ public function supports(Request $request): ?bool return $this->authenticator->supports($request); } - public function authenticate(Request $request): PassportInterface + public function authenticate(Request $request): Passport { $passport = $this->authenticator->authenticate($request); $passport->addBadge(new LdapBadge($this->ldapServiceId, $this->dnString, $this->searchDn, $this->searchPassword, $this->queryString)); @@ -61,9 +62,23 @@ public function authenticate(Request $request): PassportInterface return $passport; } + /** + * @deprecated since Symfony 5.4, use {@link createToken()} instead + */ public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface { - return $this->authenticator->createAuthenticatedToken($passport, $firewallName); + trigger_deprecation('symfony/ldap', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__); + + return $this->createToken($passport, $firewallName); + } + + public function createToken(PassportInterface $passport, string $firewallName): TokenInterface + { + // @deprecated since Symfony 5.4, in 6.0 change to: + // return $this->authenticator->createToken($passport, $firewallName); + return method_exists($this->authenticator, 'createToken') + ? $this->authenticator->createToken($passport, $firewallName) + : $this->authenticator->createAuthenticatedToken($passport, $firewallName); } public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response diff --git a/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php b/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php index b45c948acd353..e3fce37b9a049 100644 --- a/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php +++ b/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Security\Core\Exception; /** - * AuthenticationExpiredException is thrown when an authenticated token becomes un-authenticated between requests. + * AuthenticationExpiredException is thrown when an authentication token becomes un-authenticated between requests. * * In practice, this is due to the User changing between requests (e.g. password changes), * causes the token to become un-authenticated. diff --git a/src/Symfony/Component/Security/Http/Authentication/AuthenticatorManager.php b/src/Symfony/Component/Security/Http/Authentication/AuthenticatorManager.php index e72eb075b163e..703efdfa61043 100644 --- a/src/Symfony/Component/Security/Http/Authentication/AuthenticatorManager.php +++ b/src/Symfony/Component/Security/Http/Authentication/AuthenticatorManager.php @@ -74,11 +74,12 @@ public function __construct(iterable $authenticators, TokenStorageInterface $tok */ public function authenticateUser(UserInterface $user, AuthenticatorInterface $authenticator, Request $request, array $badges = []): ?Response { - // create an authenticated token for the User + // create an authentication token for the User // @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0 - $token = $authenticator->createAuthenticatedToken($passport = new SelfValidatingPassport(new UserBadge(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), function () use ($user) { return $user; }), $badges), $this->firewallName); + $passport = new SelfValidatingPassport(new UserBadge(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), function () use ($user) { return $user; }), $badges); + $token = method_exists($authenticator, 'createToken') ? $authenticator->createToken($passport, $this->firewallName) : $authenticator->createAuthenticatedToken($passport, $this->firewallName); - // announce the authenticated token + // announce the authentication token $token = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($token, $passport))->getAuthenticatedToken(); // authenticate this in the system @@ -189,10 +190,10 @@ private function executeAuthenticator(AuthenticatorInterface $authenticator, Req throw new BadCredentialsException(sprintf('Authentication failed; Some badges marked as required by the firewall config are not available on the passport: "%s".', implode('", "', $missingRequiredBadges))); } - // create the authenticated token - $authenticatedToken = $authenticator->createAuthenticatedToken($passport, $this->firewallName); + // create the authentication token + $authenticatedToken = method_exists($authenticator, 'createToken') ? $authenticator->createToken($passport, $this->firewallName) : $authenticator->createAuthenticatedToken($passport, $this->firewallName); - // announce the authenticated token + // announce the authentication token $authenticatedToken = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($authenticatedToken, $passport))->getAuthenticatedToken(); if (true === $this->eraseCredentials) { diff --git a/src/Symfony/Component/Security/Http/Authenticator/AbstractAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/AbstractAuthenticator.php index fb7df4db12872..3feab09ec0b14 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/AbstractAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/AbstractAuthenticator.php @@ -13,6 +13,7 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\LogicException; +use Symfony\Component\Security\Http\Authenticator\Passport\Passport; use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface; use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface; use Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken; @@ -30,12 +31,23 @@ abstract class AbstractAuthenticator implements AuthenticatorInterface * * @return PostAuthenticationToken */ + public function createToken(Passport $passport, string $firewallName): TokenInterface + { + return new PostAuthenticationToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles()); + } + + /** + * @deprecated since Symfony 5.4, use {@link createToken()} instead + */ public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface { + // @deprecated since Symfony 5.4 if (!$passport instanceof UserPassportInterface) { - throw new LogicException(sprintf('Passport does not contain a user, overwrite "createAuthenticatedToken()" in "%s" to create a custom authenticated token.', static::class)); + throw new LogicException(sprintf('Passport does not contain a user, overwrite "createToken()" in "%s" to create a custom authentication token.', static::class)); } - return new PostAuthenticationToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles()); + trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__); + + return $this->createToken($passport, $firewallName); } } diff --git a/src/Symfony/Component/Security/Http/Authenticator/AbstractPreAuthenticatedAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/AbstractPreAuthenticatedAuthenticator.php index 1202444a1b647..b7e44c4e548f0 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/AbstractPreAuthenticatedAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/AbstractPreAuthenticatedAuthenticator.php @@ -22,6 +22,7 @@ use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PreAuthenticatedUserBadge; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; +use Symfony\Component\Security\Http\Authenticator\Passport\Passport; use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface; use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; @@ -84,7 +85,7 @@ public function supports(Request $request): ?bool return true; } - public function authenticate(Request $request): PassportInterface + public function authenticate(Request $request): Passport { // @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0 $method = 'loadUserByIdentifier'; @@ -100,7 +101,17 @@ public function authenticate(Request $request): PassportInterface ); } + /** + * @deprecated since Symfony 5.4, use {@link createToken()} instead + */ public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface + { + trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__); + + return $this->createToken($passport, $firewallName); + } + + public function createToken(Passport $passport, string $firewallName): TokenInterface { return new PreAuthenticatedToken($passport->getUser(), null, $firewallName, $passport->getUser()->getRoles()); } diff --git a/src/Symfony/Component/Security/Http/Authenticator/AuthenticatorInterface.php b/src/Symfony/Component/Security/Http/Authenticator/AuthenticatorInterface.php index 65eb8738b791c..e29b4cd93e091 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/AuthenticatorInterface.php +++ b/src/Symfony/Component/Security/Http/Authenticator/AuthenticatorInterface.php @@ -15,6 +15,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Http\Authenticator\Passport\Passport; use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface; /** @@ -23,6 +24,10 @@ * @author Ryan Weaver * @author Amaury Leroux de Lens * @author Wouter de Jong + * + * @method TokenInterface createToken(Passport $passport, string $firewallName) Creates a token for the given user. + * If you don't care about which token class is used, you can skip this method by extending + * the AbstractAuthenticator class from your authenticator. */ interface AuthenticatorInterface { @@ -47,8 +52,10 @@ public function supports(Request $request): ?bool; * a UserNotFoundException when the user cannot be found). * * @throws AuthenticationException + * + * @return Passport */ - public function authenticate(Request $request): PassportInterface; + public function authenticate(Request $request); /*: Passport;*/ /** * Create an authenticated token for the given user. @@ -60,6 +67,8 @@ public function authenticate(Request $request): PassportInterface; * @see AbstractAuthenticator * * @param PassportInterface $passport The passport returned from authenticate() + * + * @deprecated since Symfony 5.4, use {@link createToken()} instead */ public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface; diff --git a/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php index 892f19a9a66bf..2f54fd33d102d 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php @@ -77,7 +77,7 @@ public function supports(Request $request): bool && $this->httpUtils->checkRequestPath($request, $this->options['check_path']); } - public function authenticate(Request $request): PassportInterface + public function authenticate(Request $request): Passport { $credentials = $this->getCredentials($request); @@ -106,9 +106,19 @@ public function authenticate(Request $request): PassportInterface } /** - * @param Passport $passport + * @deprecated since Symfony 5.4, use {@link createToken()} instead */ public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface + { + trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__); + + return $this->createToken($passport, $firewallName); + } + + /** + * @return UsernamePasswordToken + */ + public function createToken(Passport $passport, string $firewallName): TokenInterface { return new UsernamePasswordToken($passport->getUser(), null, $firewallName, $passport->getUser()->getRoles()); } diff --git a/src/Symfony/Component/Security/Http/Authenticator/HttpBasicAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/HttpBasicAuthenticator.php index 55ef80d80d492..6dec3a9708fd7 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/HttpBasicAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/HttpBasicAuthenticator.php @@ -84,9 +84,16 @@ public function authenticate(Request $request): PassportInterface } /** - * @param Passport $passport + * @deprecated since Symfony 5.4, use {@link createToken()} instead */ public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface + { + trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__); + + return $this->createToken($passport, $firewallName); + } + + public function createToken(Passport $passport, string $firewallName): TokenInterface { return new UsernamePasswordToken($passport->getUser(), null, $firewallName, $passport->getUser()->getRoles()); } diff --git a/src/Symfony/Component/Security/Http/Authenticator/JsonLoginAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/JsonLoginAuthenticator.php index 41e04aef3d763..34d8ede926a09 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/JsonLoginAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/JsonLoginAuthenticator.php @@ -110,7 +110,17 @@ public function authenticate(Request $request): PassportInterface return $passport; } + /** + * @deprecated since Symfony 5.4, use {@link createToken()} instead + */ public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface + { + trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__); + + return $this->createToken($passport, $firewallName); + } + + public function createToken(Passport $passport, string $firewallName): TokenInterface { return new UsernamePasswordToken($passport->getUser(), null, $firewallName, $passport->getUser()->getRoles()); } diff --git a/src/Symfony/Component/Security/Http/Authenticator/Passport/PassportInterface.php b/src/Symfony/Component/Security/Http/Authenticator/Passport/PassportInterface.php index 46fecf9b5d703..8f7341f0df045 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/Passport/PassportInterface.php +++ b/src/Symfony/Component/Security/Http/Authenticator/Passport/PassportInterface.php @@ -21,6 +21,8 @@ * passport. * * @author Wouter de Jong + * + * @deprecated since Symfony 5.4, use {@link Passport} instead */ interface PassportInterface { diff --git a/src/Symfony/Component/Security/Http/Authenticator/Passport/UserPassportInterface.php b/src/Symfony/Component/Security/Http/Authenticator/Passport/UserPassportInterface.php index 5c13d3bbd28c2..319c2952dfeae 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/Passport/UserPassportInterface.php +++ b/src/Symfony/Component/Security/Http/Authenticator/Passport/UserPassportInterface.php @@ -18,6 +18,8 @@ * Represents a passport for a Security User. * * @author Wouter de Jong + * + * @deprecated since Symfony 5.4, use {@link Passport} instead */ interface UserPassportInterface extends PassportInterface { diff --git a/src/Symfony/Component/Security/Http/Authenticator/RememberMeAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/RememberMeAuthenticator.php index d47b10189aeb8..cca50c8b2d82f 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/RememberMeAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/RememberMeAuthenticator.php @@ -22,6 +22,7 @@ use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; +use Symfony\Component\Security\Http\Authenticator\Passport\Passport; use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface; use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; use Symfony\Component\Security\Http\RememberMe\RememberMeDetails; @@ -95,7 +96,17 @@ public function authenticate(Request $request): PassportInterface })); } + /** + * @deprecated since Symfony 5.4, use {@link createToken()} instead + */ public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface + { + trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__); + + return $this->createToken($passport, $firewallName); + } + + public function createToken(Passport $passport, string $firewallName): TokenInterface { return new RememberMeToken($passport->getUser(), $firewallName, $this->secret); } diff --git a/src/Symfony/Component/Security/Http/Authenticator/Token/PostAuthenticationToken.php b/src/Symfony/Component/Security/Http/Authenticator/Token/PostAuthenticationToken.php index 554fec09fff8a..7b3b24b7a753a 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/Token/PostAuthenticationToken.php +++ b/src/Symfony/Component/Security/Http/Authenticator/Token/PostAuthenticationToken.php @@ -40,7 +40,7 @@ public function __construct(UserInterface $user, string $firewallName, array $ro } /** - * This is meant to be only an authenticated token, where credentials + * This is meant to be only a token, where credentials * have already been used and are thus cleared. * * {@inheritdoc} diff --git a/src/Symfony/Component/Security/Http/CHANGELOG.md b/src/Symfony/Component/Security/Http/CHANGELOG.md index 2b14bda5a8ca0..664fcf86f4e9f 100644 --- a/src/Symfony/Component/Security/Http/CHANGELOG.md +++ b/src/Symfony/Component/Security/Http/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * Deprecate `DeauthenticatedEvent`, use `TokenDeauthenticatedEvent` instead * Deprecate `CookieClearingLogoutHandler`, `SessionLogoutHandler` and `CsrfTokenClearingLogoutHandler`. Use `CookieClearingLogoutListener`, `SessionLogoutListener` and `CsrfTokenClearingLogoutListener` instead + * Deprecate `PassportInterface` and `UserPassportInterface`, use `Passport` instead 5.3 --- diff --git a/src/Symfony/Component/Security/Http/Event/LoginSuccessEvent.php b/src/Symfony/Component/Security/Http/Event/LoginSuccessEvent.php index 4c4c0f634e17f..1d736241e2764 100644 --- a/src/Symfony/Component/Security/Http/Event/LoginSuccessEvent.php +++ b/src/Symfony/Component/Security/Http/Event/LoginSuccessEvent.php @@ -24,8 +24,8 @@ /** * This event is dispatched after authentication has successfully completed. * - * At this stage, the authenticator created an authenticated token - * and generated an authentication success response. Listeners to + * At this stage, the authenticator created a token and + * generated an authentication success response. Listeners to * this event can do actions related to successful authentication * (such as migrating the password). * diff --git a/src/Symfony/Component/Security/Http/Tests/Authentication/AuthenticatorManagerTest.php b/src/Symfony/Component/Security/Http/Tests/Authentication/AuthenticatorManagerTest.php index 1ab02c998f2b4..8e36110711dd8 100644 --- a/src/Symfony/Component/Security/Http/Tests/Authentication/AuthenticatorManagerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Authentication/AuthenticatorManagerTest.php @@ -106,7 +106,7 @@ public function testAuthenticateRequest($matchingAuthenticatorIndex) $listenerCalled = true; } }); - $matchingAuthenticator->expects($this->any())->method('createAuthenticatedToken')->willReturn($this->token); + $matchingAuthenticator->expects($this->any())->method('createToken')->willReturn($this->token); $this->tokenStorage->expects($this->once())->method('setToken')->with($this->token); @@ -159,7 +159,7 @@ public function testAllRequiredBadgesPresent() $csrfBadge = new CsrfTokenBadge('csrfid', 'csrftoken'); $csrfBadge->markResolved(); $authenticator->expects($this->any())->method('authenticate')->willReturn(new SelfValidatingPassport(new UserBadge('wouter'), [$csrfBadge])); - $authenticator->expects($this->any())->method('createAuthenticatedToken')->willReturn(new UsernamePasswordToken($this->user, null, 'main')); + $authenticator->expects($this->any())->method('createToken')->willReturn(new UsernamePasswordToken($this->user, null, 'main')); $authenticator->expects($this->once())->method('onAuthenticationSuccess'); @@ -177,7 +177,7 @@ public function testEraseCredentials($eraseCredentials) $authenticator->expects($this->any())->method('authenticate')->willReturn(new SelfValidatingPassport(new UserBadge('wouter', function () { return $this->user; }))); - $authenticator->expects($this->any())->method('createAuthenticatedToken')->willReturn($this->token); + $authenticator->expects($this->any())->method('createToken')->willReturn($this->token); $this->token->expects($eraseCredentials ? $this->once() : $this->never())->method('eraseCredentials'); @@ -198,7 +198,7 @@ public function testAuthenticateRequestCanModifyTokenFromEvent() $authenticator->expects($this->any())->method('authenticate')->willReturn(new SelfValidatingPassport(new UserBadge('wouter', function () { return $this->user; }))); - $authenticator->expects($this->any())->method('createAuthenticatedToken')->willReturn($this->token); + $authenticator->expects($this->any())->method('createToken')->willReturn($this->token); $modifiedToken = $this->createMock(TokenInterface::class); $modifiedToken->expects($this->any())->method('getUser')->willReturn($this->user); @@ -218,7 +218,7 @@ public function testAuthenticateRequestCanModifyTokenFromEvent() public function testAuthenticateUser() { $authenticator = $this->createAuthenticator(); - $authenticator->expects($this->any())->method('createAuthenticatedToken')->willReturn($this->token); + $authenticator->expects($this->any())->method('createToken')->willReturn($this->token); $authenticator->expects($this->any())->method('onAuthenticationSuccess')->willReturn($this->response); $this->tokenStorage->expects($this->once())->method('setToken')->with($this->token); @@ -230,7 +230,7 @@ public function testAuthenticateUser() public function testAuthenticateUserCanModifyTokenFromEvent() { $authenticator = $this->createAuthenticator(); - $authenticator->expects($this->any())->method('createAuthenticatedToken')->willReturn($this->token); + $authenticator->expects($this->any())->method('createToken')->willReturn($this->token); $authenticator->expects($this->any())->method('onAuthenticationSuccess')->willReturn($this->response); $modifiedToken = $this->createMock(TokenInterface::class); @@ -249,6 +249,27 @@ public function testAuthenticateUserCanModifyTokenFromEvent() } public function testInteractiveAuthenticator() + { + $authenticator = $this->createMock(TestInteractiveAuthenticator::class); + $authenticator->expects($this->any())->method('isInteractive')->willReturn(true); + $this->request->attributes->set('_security_authenticators', [$authenticator]); + + $authenticator->expects($this->any())->method('authenticate')->willReturn(new SelfValidatingPassport(new UserBadge('wouter', function () { return $this->user; }))); + $authenticator->expects($this->any())->method('createToken')->willReturn($this->token); + + $this->tokenStorage->expects($this->once())->method('setToken')->with($this->token); + + $authenticator->expects($this->any()) + ->method('onAuthenticationSuccess') + ->with($this->anything(), $this->token, 'main') + ->willReturn($this->response); + + $manager = $this->createManager([$authenticator]); + $response = $manager->authenticateRequest($this->request); + $this->assertSame($this->response, $response); + } + + public function testLegacyInteractiveAuthenticator() { $authenticator = $this->createMock(InteractiveAuthenticatorInterface::class); $authenticator->expects($this->any())->method('isInteractive')->willReturn(true); @@ -272,7 +293,7 @@ public function testInteractiveAuthenticator() public function testAuthenticateRequestHidesInvalidUserExceptions() { $invalidUserException = new UserNotFoundException(); - $authenticator = $this->createMock(InteractiveAuthenticatorInterface::class); + $authenticator = $this->createMock(TestInteractiveAuthenticator::class); $this->request->attributes->set('_security_authenticators', [$authenticator]); $authenticator->expects($this->any())->method('authenticate')->willThrowException($invalidUserException); @@ -291,7 +312,7 @@ public function testAuthenticateRequestHidesInvalidUserExceptions() private function createAuthenticator($supports = true) { - $authenticator = $this->createMock(InteractiveAuthenticatorInterface::class); + $authenticator = $this->createMock(TestInteractiveAuthenticator::class); $authenticator->expects($this->any())->method('supports')->willReturn($supports); return $authenticator; @@ -302,3 +323,10 @@ private function createManager($authenticators, $firewallName = 'main', $eraseCr return new AuthenticatorManager($authenticators, $this->tokenStorage, $this->eventDispatcher, $firewallName, null, $eraseCredentials, true, $requiredBadges); } } + +abstract class TestInteractiveAuthenticator implements InteractiveAuthenticatorInterface +{ + public function createToken(Passport $passport, string $firewallName): TokenInterface + { + } +}