1
0
mirror of synced 2024-11-28 15:46:04 +03:00

Fix authenticators and dependecy injection

This commit is contained in:
Кривич Сергей 2022-07-21 13:02:32 +03:00
parent 6243bd1261
commit 180ccab466
8 changed files with 36 additions and 57 deletions

View File

@ -66,8 +66,8 @@ class RetailCrmServiceExtension extends Extension
$container $container
->register(CallbackValueResolver::class) ->register(CallbackValueResolver::class)
->setArguments([ ->setArguments([
new Reference($container->getParameter('retail_crm_service.request_schema.callback.serializer')),
new Reference('validator'), new Reference('validator'),
new Reference($container->getParameter('retail_crm_service.request_schema.callback.serializer')),
$container->getParameter('retail_crm_service.request_schema.callback.supports') $container->getParameter('retail_crm_service.request_schema.callback.supports')
]) ])
->addTag('controller.argument_value_resolver', ['priority' => 50]) ->addTag('controller.argument_value_resolver', ['priority' => 50])
@ -76,8 +76,8 @@ class RetailCrmServiceExtension extends Extension
$container $container
->register(ClientValueResolver::class) ->register(ClientValueResolver::class)
->setArguments([ ->setArguments([
new Reference($container->getParameter('retail_crm_service.request_schema.client.serializer')),
new Reference('validator'), new Reference('validator'),
new Reference($container->getParameter('retail_crm_service.request_schema.client.serializer')),
$container->getParameter('retail_crm_service.request_schema.client.supports') $container->getParameter('retail_crm_service.request_schema.client.supports')
]) ])
->addTag('controller.argument_value_resolver', ['priority' => 50]) ->addTag('controller.argument_value_resolver', ['priority' => 50])

View File

@ -23,12 +23,13 @@ security:
custom_authenticators: custom_authenticators:
- RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator - RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator
front: front:
pattern: ^/(front|login) pattern: ^/auth
provider: connection provider: connection
stateless: false stateless: false
remember_me: remember_me:
secret: '%kernel.secret%' secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds lifetime: 604800 # 1 week in seconds
signature_properties: ['clientId']
always_remember_me: true always_remember_me: true
custom_authenticators: custom_authenticators:
- RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator - RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator
@ -41,33 +42,27 @@ security:
- { path: ^/simple-connection, roles: PUBLIC_ACCESS } - { path: ^/simple-connection, roles: PUBLIC_ACCESS }
``` ```
To authenticate the user after creating it, you can use the following code Login controller will be called after the authenticator successfully authenticates the user. You can get the authenticated user, generate a token (or whatever you need to return) and return response:
```php ```php
use App\Entity\Connection; use App\Entity\User;
use App\Services\ConnectionManager; use Symfony\Component\Security\Http\Attribute\CurrentUser;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
use RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator;
class AppController extends AbstractController class ApiLoginController extends AbstractController
{ {
public function someAction( #[Route('/auth', name: 'auth')]
Request $request, public function auth(#[CurrentUser] ?User $user): Response
Connection $connection, {
ConnectionManager $manager, $token = ...; // somehow create an API token for $user
UserAuthenticatorInterface $userAuthenticator,
FrontApiClientAuthenticator $authenticator
): Response {
$exist = $manager->search($connection); //get connection
$userAuthenticator->authenticateUser( return $this->json([
$connection, 'user' => $user->getUserIdentifier(),
$authenticator, 'token' => $token,
$request ]);
);
} }
} }
``` ```
The <code>#[CurrentUser]</code> can only be used in controller arguments to retrieve the authenticated user. In services, you would use getUser().

View File

@ -16,8 +16,6 @@ abstract class AbstractClientAuthenticator extends AbstractAuthenticator
{ {
public const AUTH_FIELD = 'clientId'; public const AUTH_FIELD = 'clientId';
protected ObjectRepository $userRepository;
public function __construct(private ErrorJsonResponseFactory $errorResponseFactory) public function __construct(private ErrorJsonResponseFactory $errorResponseFactory)
{ {
} }
@ -38,9 +36,4 @@ abstract class AbstractClientAuthenticator extends AbstractAuthenticator
{ {
return null; return null;
} }
public function setUserRepository(ObjectRepository $userRepository): void
{
$this->userRepository = $userRepository;
}
} }

View File

@ -24,8 +24,7 @@ class CallbackClientAuthenticator extends AbstractClientAuthenticator
return new SelfValidatingPassport( return new SelfValidatingPassport(
new UserBadge( new UserBadge(
$identifier, $identifier
fn ($userIdentifier) => $this->userRepository->findOneBy([static::AUTH_FIELD => $userIdentifier])
), ),
[] []
); );

View File

@ -38,8 +38,7 @@ class FrontApiClientAuthenticator extends AbstractClientAuthenticator
return new SelfValidatingPassport( return new SelfValidatingPassport(
new UserBadge( new UserBadge(
$identifier, $identifier
fn ($userIdentifier) => $this->userRepository->findOneBy([static::AUTH_FIELD => $userIdentifier]),
), ),
[new RememberMeBadge()] [new RememberMeBadge()]
); );

View File

@ -6,6 +6,8 @@ use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface class User implements UserInterface
{ {
protected string $clientId = '123';
public function getRoles(): array public function getRoles(): array
{ {
return ["USER"]; return ["USER"];
@ -22,6 +24,6 @@ class User implements UserInterface
public function getUserIdentifier(): string public function getUserIdentifier(): string
{ {
return 'identifier'; return $this->clientId;
} }
} }

View File

@ -12,6 +12,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
class CallbackClientAuthenticatorTest extends TestCase class CallbackClientAuthenticatorTest extends TestCase
{ {
@ -58,19 +59,13 @@ class CallbackClientAuthenticatorTest extends TestCase
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class); $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
$user = new User(); $user = new User();
$userRepository = $this->createMock(ObjectRepository::class);
$userRepository
->expects(static::once())
->method('findOneBy')
->willReturn($user)
;
$auth = new CallbackClientAuthenticator($errorResponseFactory); $auth = new CallbackClientAuthenticator($errorResponseFactory);
$auth->setUserRepository($userRepository);
$passport = $auth->authenticate(new Request([], [CallbackClientAuthenticator::AUTH_FIELD => '123'])); $passport = $auth->authenticate(new Request([], [CallbackClientAuthenticator::AUTH_FIELD => '123']));
$authUser = $passport->getUser(); static::assertTrue($passport->hasBadge(UserBadge::class));
static::assertEquals($user, $authUser); static::assertEquals(
$user->getUserIdentifier(),
$passport->getBadge(UserBadge::class)->getUserIdentifier()
);
$this->expectException(AuthenticationException::class); $this->expectException(AuthenticationException::class);
$auth->authenticate(new Request()); $auth->authenticate(new Request());

View File

@ -13,6 +13,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
class FrontApiClientAuthenticatorTest extends TestCase class FrontApiClientAuthenticatorTest extends TestCase
{ {
@ -65,19 +66,14 @@ class FrontApiClientAuthenticatorTest extends TestCase
$security = $this->createMock(Security::class); $security = $this->createMock(Security::class);
$user = new User(); $user = new User();
$userRepository = $this->createMock(ObjectRepository::class);
$userRepository
->expects(static::once())
->method('findOneBy')
->with([FrontApiClientAuthenticator::AUTH_FIELD => '123'])
->willReturn($user)
;
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security); $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
$auth->setUserRepository($userRepository);
$passport = $auth->authenticate(new Request([], [FrontApiClientAuthenticator::AUTH_FIELD => '123'])); $passport = $auth->authenticate(new Request([], [FrontApiClientAuthenticator::AUTH_FIELD => '123']));
$authUser = $passport->getUser(); static::assertTrue($passport->hasBadge(UserBadge::class));
static::assertEquals($user, $authUser); static::assertEquals(
$user->getUserIdentifier(),
$passport->getBadge(UserBadge::class)->getUserIdentifier()
);
$this->expectException(AuthenticationException::class); $this->expectException(AuthenticationException::class);
$auth->authenticate(new Request()); $auth->authenticate(new Request());