From 26e30b9ce613358276f71512ef52a8e3abd593eb Mon Sep 17 00:00:00 2001 From: Joseph Bielawski Date: Fri, 9 Feb 2024 17:42:16 +0100 Subject: [PATCH] Replace custom authenticator passport with custom badge usage --- .../Http/Authenticator/OAuthAuthenticator.php | 25 ++++++--- .../Passport/Badge/OAuthTokenBadge.php | 37 ++++++++++++++ .../Passport/SelfValidatedOAuthPassport.php | 51 ------------------- .../Authenticator/OAuthAuthenticatorTest.php | 11 +--- 4 files changed, 57 insertions(+), 67 deletions(-) create mode 100644 src/Security/Http/Authenticator/Passport/Badge/OAuthTokenBadge.php delete mode 100644 src/Security/Http/Authenticator/Passport/SelfValidatedOAuthPassport.php diff --git a/src/Security/Http/Authenticator/OAuthAuthenticator.php b/src/Security/Http/Authenticator/OAuthAuthenticator.php index 1196496df..7c431d726 100644 --- a/src/Security/Http/Authenticator/OAuthAuthenticator.php +++ b/src/Security/Http/Authenticator/OAuthAuthenticator.php @@ -16,7 +16,7 @@ use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken; use HWI\Bundle\OAuthBundle\Security\Core\Exception\OAuthAwareExceptionInterface; use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface; -use HWI\Bundle\OAuthBundle\Security\Http\Authenticator\Passport\SelfValidatedOAuthPassport; +use HWI\Bundle\OAuthBundle\Security\Http\Authenticator\Passport\Badge\OAuthTokenBadge; use HWI\Bundle\OAuthBundle\Security\Http\ResourceOwnerMapInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; @@ -32,7 +32,9 @@ use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface; use Symfony\Component\Security\Http\Authenticator\InteractiveAuthenticatorInterface; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge; +use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; use Symfony\Component\Security\Http\Authenticator\Passport\Passport; +use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Symfony\Component\Security\Http\HttpUtils; @@ -139,8 +141,18 @@ public function authenticate(Request $request): Passport $token = new OAuthToken($accessToken); $token->setResourceOwnerName($resourceOwner->getName()); + $token = $this->refreshToken($token); - return new SelfValidatedOAuthPassport($this->refreshToken($token), [new RememberMeBadge()]); + $user = $token->getUser(); + + $userBadge = class_exists(UserBadge::class) + ? new UserBadge( + $user ? method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername() : null, + static function () use ($user) { return $user; } + ) + : $user; + + return new SelfValidatingPassport($userBadge, [new RememberMeBadge(), new OAuthTokenBadge($token)]); } /** @@ -246,15 +258,16 @@ public function createToken(Passport $passport, string $firewallName): TokenInte } /** - * @param Passport|SelfValidatedOAuthPassport $passport + * @param Passport $passport */ public function createAuthenticatedToken($passport, string $firewallName): TokenInterface { - if ($passport instanceof SelfValidatedOAuthPassport) { - return $passport->getToken(); + $badge = $passport->getBadge(OAuthTokenBadge::class); + if ($badge instanceof OAuthTokenBadge) { + return $badge->getToken(); } - throw new \LogicException(sprintf('The first argument of "%s" must be instance of "%s", "%s" provided.', __METHOD__, SelfValidatedOAuthPassport::class, $passport::class)); + throw new \LogicException(sprintf('Given passport must contain instance of "%s".', OAuthTokenBadge::class)); } public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response diff --git a/src/Security/Http/Authenticator/Passport/Badge/OAuthTokenBadge.php b/src/Security/Http/Authenticator/Passport/Badge/OAuthTokenBadge.php new file mode 100644 index 000000000..e81875920 --- /dev/null +++ b/src/Security/Http/Authenticator/Passport/Badge/OAuthTokenBadge.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace HWI\Bundle\OAuthBundle\Security\Http\Authenticator\Passport\Badge; + +use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken; +use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface; + +final class OAuthTokenBadge implements BadgeInterface +{ + private OAuthToken $token; + + public function __construct(OAuthToken $token) + { + $this->token = $token; + } + + public function isResolved(): bool + { + return true; + } + + public function getToken(): OAuthToken + { + return $this->token; + } +} diff --git a/src/Security/Http/Authenticator/Passport/SelfValidatedOAuthPassport.php b/src/Security/Http/Authenticator/Passport/SelfValidatedOAuthPassport.php deleted file mode 100644 index 3d60e4f77..000000000 --- a/src/Security/Http/Authenticator/Passport/SelfValidatedOAuthPassport.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace HWI\Bundle\OAuthBundle\Security\Http\Authenticator\Passport; - -use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken; -use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface; -use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; -use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; - -/** - * SelfValidatingPassport contained OAuthToken. - */ -final class SelfValidatedOAuthPassport extends SelfValidatingPassport -{ - private OAuthToken $token; - - /** - * Token already contains authenticated user. No need to create trivial UserBadge outside. - * - * @param BadgeInterface[] $badges - */ - public function __construct(OAuthToken $token, array $badges = []) - { - $this->token = $token; - - $user = $token->getUser(); - - $userBadge = class_exists(UserBadge::class) - ? new UserBadge( - method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), - static function () use ($user) { return $user; } - ) - : $user; - - parent::__construct($userBadge, $badges); - } - - public function getToken(): OAuthToken - { - return $this->token; - } -} diff --git a/tests/Security/Http/Authenticator/OAuthAuthenticatorTest.php b/tests/Security/Http/Authenticator/OAuthAuthenticatorTest.php index dbf75a769..667174c25 100644 --- a/tests/Security/Http/Authenticator/OAuthAuthenticatorTest.php +++ b/tests/Security/Http/Authenticator/OAuthAuthenticatorTest.php @@ -31,7 +31,6 @@ use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; -use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface; use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; use Symfony\Component\Security\Http\HttpUtils; @@ -40,14 +39,6 @@ */ final class OAuthAuthenticatorTest extends TestCase { - protected function setUp(): void - { - // Symfony < 5.1 BC layer. - if (!interface_exists(AuthenticatorInterface::class)) { - $this->markTestSkipped('Symfony new Authenticator-based security system is not available.'); - } - } - public function testSupports(): void { $httpUtilsMock = $this->getHttpUtilsMock(); @@ -162,7 +153,7 @@ public function testAuthenticate(): void $this->assertEquals($user, $passport->getUser()); /** @var AbstractOAuthToken $token */ - $token = $authenticator->createAuthenticatedToken($passport, 'main'); + $token = $authenticator->createToken($passport, 'main'); $this->assertInstanceOf(OAuthToken::class, $token); $this->assertEquals($resourceOwnerName, $token->getResourceOwnerName()); $this->assertEquals($user, $token->getUser());