Update authenticator && documentation
This commit is contained in:
parent
180ccab466
commit
a61d276a83
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#### Callbacks (form data)
|
#### Callbacks (form data)
|
||||||
|
|
||||||
|
> For successful deserialization of an entity, there must be setters for the passed parameters
|
||||||
|
|
||||||
To automatically get the callback request parameter
|
To automatically get the callback request parameter
|
||||||
|
|
||||||
```php
|
```php
|
||||||
|
@ -16,21 +16,10 @@ security:
|
|||||||
pattern: ^/simple-connection
|
pattern: ^/simple-connection
|
||||||
stateless: true
|
stateless: true
|
||||||
security: false
|
security: false
|
||||||
callback:
|
front:
|
||||||
pattern: ^/callback
|
pattern: ^/front
|
||||||
provider: connection
|
provider: connection
|
||||||
stateless: true
|
stateless: true
|
||||||
custom_authenticators:
|
|
||||||
- RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator
|
|
||||||
front:
|
|
||||||
pattern: ^/auth
|
|
||||||
provider: connection
|
|
||||||
stateless: false
|
|
||||||
remember_me:
|
|
||||||
secret: '%kernel.secret%'
|
|
||||||
lifetime: 604800 # 1 week in seconds
|
|
||||||
signature_properties: ['clientId']
|
|
||||||
always_remember_me: true
|
|
||||||
custom_authenticators:
|
custom_authenticators:
|
||||||
- RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator
|
- RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator
|
||||||
main:
|
main:
|
||||||
@ -38,8 +27,8 @@ security:
|
|||||||
lazy: true
|
lazy: true
|
||||||
|
|
||||||
access_control:
|
access_control:
|
||||||
- { path: ^/front, roles: IS_AUTHENTICATED_REMEMBERED }
|
- { path: ^/front, roles: IS_AUTHENTICATED_FULLY }
|
||||||
- { path: ^/simple-connection, roles: PUBLIC_ACCESS }
|
- { path: ^/(simple-connection), roles: PUBLIC_ACCESS }
|
||||||
```
|
```
|
||||||
|
|
||||||
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:
|
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:
|
||||||
@ -51,8 +40,8 @@ Login controller will be called after the authenticator successfully authenticat
|
|||||||
|
|
||||||
class ApiLoginController extends AbstractController
|
class ApiLoginController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/auth', name: 'auth')]
|
#[Route('/front', name: 'front')]
|
||||||
public function auth(#[CurrentUser] ?User $user): Response
|
public function front(#[CurrentUser] ?User $user): Response
|
||||||
{
|
{
|
||||||
$token = ...; // somehow create an API token for $user
|
$token = ...; // somehow create an API token for $user
|
||||||
|
|
||||||
@ -66,3 +55,7 @@ Login controller will be called after the authenticator successfully authenticat
|
|||||||
```
|
```
|
||||||
|
|
||||||
The <code>#[CurrentUser]</code> can only be used in controller arguments to retrieve the authenticated user. In services, you would use getUser().
|
The <code>#[CurrentUser]</code> can only be used in controller arguments to retrieve the authenticated user. In services, you would use getUser().
|
||||||
|
|
||||||
|
See the [manual](https://symfony.com/doc/6.0/security.html) for more information.
|
||||||
|
|
||||||
|
> If you set the parameter stateless: false, then during an active session the login will be made on the basis of the data deserialized from the session storage
|
@ -6,12 +6,11 @@ use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
|
|||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
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\RememberMeBadge;
|
|
||||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||||
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
||||||
|
|
||||||
class FrontApiClientAuthenticator extends AbstractClientAuthenticator
|
class ApiClientAuthenticator extends AbstractClientAuthenticator
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ErrorJsonResponseFactory $errorResponseFactory,
|
ErrorJsonResponseFactory $errorResponseFactory,
|
||||||
@ -40,7 +39,7 @@ class FrontApiClientAuthenticator extends AbstractClientAuthenticator
|
|||||||
new UserBadge(
|
new UserBadge(
|
||||||
$identifier
|
$identifier
|
||||||
),
|
),
|
||||||
[new RememberMeBadge()]
|
[]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace RetailCrm\ServiceBundle\Security;
|
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
|
||||||
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;
|
|
||||||
|
|
||||||
class CallbackClientAuthenticator extends AbstractClientAuthenticator
|
|
||||||
{
|
|
||||||
public function supports(Request $request): bool
|
|
||||||
{
|
|
||||||
return $request->request->has(static::AUTH_FIELD) || $request->query->has(static::AUTH_FIELD);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function authenticate(Request $request): Passport
|
|
||||||
{
|
|
||||||
$identifier = $request->request->get(static::AUTH_FIELD);
|
|
||||||
if (null === $identifier) {
|
|
||||||
throw new AuthenticationException('Request does not contain authentication data');
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SelfValidatingPassport(
|
|
||||||
new UserBadge(
|
|
||||||
$identifier
|
|
||||||
),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
namespace RetailCrm\ServiceBundle\Tests\Security;
|
namespace RetailCrm\ServiceBundle\Tests\Security;
|
||||||
|
|
||||||
use Doctrine\Persistence\ObjectRepository;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
|
use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
|
||||||
use RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator;
|
use RetailCrm\ServiceBundle\Security\ApiClientAuthenticator;
|
||||||
use RetailCrm\ServiceBundle\Tests\DataFixtures\User;
|
use RetailCrm\ServiceBundle\Tests\DataFixtures\User;
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
@ -15,7 +14,7 @@ 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;
|
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||||
|
|
||||||
class FrontApiClientAuthenticatorTest extends TestCase
|
class ApiClientAuthenticatorTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testOnAuthenticationFailure(): void
|
public function testOnAuthenticationFailure(): void
|
||||||
{
|
{
|
||||||
@ -30,7 +29,7 @@ class FrontApiClientAuthenticatorTest extends TestCase
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
$security = $this->createMock(Security::class);
|
$security = $this->createMock(Security::class);
|
||||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
$auth = new ApiClientAuthenticator($errorResponseFactory, $security);
|
||||||
$result = $auth->onAuthenticationFailure(new Request(), new AuthenticationException());
|
$result = $auth->onAuthenticationFailure(new Request(), new AuthenticationException());
|
||||||
|
|
||||||
static::assertInstanceOf(JsonResponse::class, $result);
|
static::assertInstanceOf(JsonResponse::class, $result);
|
||||||
@ -43,7 +42,7 @@ class FrontApiClientAuthenticatorTest extends TestCase
|
|||||||
$security = $this->createMock(Security::class);
|
$security = $this->createMock(Security::class);
|
||||||
$security->method('getUser')->willReturn(new User());
|
$security->method('getUser')->willReturn(new User());
|
||||||
|
|
||||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
$auth = new ApiClientAuthenticator($errorResponseFactory, $security);
|
||||||
$result = $auth->supports(new Request());
|
$result = $auth->supports(new Request());
|
||||||
|
|
||||||
static::assertFalse($result);
|
static::assertFalse($result);
|
||||||
@ -54,8 +53,8 @@ class FrontApiClientAuthenticatorTest extends TestCase
|
|||||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||||
$security = $this->createMock(Security::class);
|
$security = $this->createMock(Security::class);
|
||||||
$security->method('getUser')->willReturn(null);
|
$security->method('getUser')->willReturn(null);
|
||||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
$auth = new ApiClientAuthenticator($errorResponseFactory, $security);
|
||||||
$result = $auth->supports(new Request([], [FrontApiClientAuthenticator::AUTH_FIELD => '123']));
|
$result = $auth->supports(new Request([], [ApiClientAuthenticator::AUTH_FIELD => '123']));
|
||||||
|
|
||||||
static::assertTrue($result);
|
static::assertTrue($result);
|
||||||
}
|
}
|
||||||
@ -66,9 +65,9 @@ class FrontApiClientAuthenticatorTest extends TestCase
|
|||||||
$security = $this->createMock(Security::class);
|
$security = $this->createMock(Security::class);
|
||||||
|
|
||||||
$user = new User();
|
$user = new User();
|
||||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
$auth = new ApiClientAuthenticator($errorResponseFactory, $security);
|
||||||
|
|
||||||
$passport = $auth->authenticate(new Request([], [FrontApiClientAuthenticator::AUTH_FIELD => '123']));
|
$passport = $auth->authenticate(new Request([], [ApiClientAuthenticator::AUTH_FIELD => '123']));
|
||||||
static::assertTrue($passport->hasBadge(UserBadge::class));
|
static::assertTrue($passport->hasBadge(UserBadge::class));
|
||||||
static::assertEquals(
|
static::assertEquals(
|
||||||
$user->getUserIdentifier(),
|
$user->getUserIdentifier(),
|
||||||
@ -86,7 +85,7 @@ class FrontApiClientAuthenticatorTest extends TestCase
|
|||||||
$request = $this->createMock(Request::class);
|
$request = $this->createMock(Request::class);
|
||||||
$token = $this->createMock(TokenInterface::class);
|
$token = $this->createMock(TokenInterface::class);
|
||||||
|
|
||||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
$auth = new ApiClientAuthenticator($errorResponseFactory, $security);
|
||||||
|
|
||||||
$result = $auth->onAuthenticationSuccess($request, $token, 'key');
|
$result = $auth->onAuthenticationSuccess($request, $token, 'key');
|
||||||
|
|
@ -1,85 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace RetailCrm\ServiceBundle\Tests\Security;
|
|
||||||
|
|
||||||
use Doctrine\Persistence\ObjectRepository;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
|
|
||||||
use RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator;
|
|
||||||
use RetailCrm\ServiceBundle\Tests\DataFixtures\User;
|
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
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\Badge\UserBadge;
|
|
||||||
|
|
||||||
class CallbackClientAuthenticatorTest extends TestCase
|
|
||||||
{
|
|
||||||
public function testOnAuthenticationFailure(): void
|
|
||||||
{
|
|
||||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
|
||||||
$errorResponseFactory
|
|
||||||
->expects(static::once())
|
|
||||||
->method('create')
|
|
||||||
->willReturn(
|
|
||||||
new JsonResponse(
|
|
||||||
['message' => 'An authentication exception occurred.'],
|
|
||||||
Response::HTTP_FORBIDDEN
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$auth = new CallbackClientAuthenticator($errorResponseFactory);
|
|
||||||
$result = $auth->onAuthenticationFailure(new Request(), new AuthenticationException());
|
|
||||||
|
|
||||||
static::assertInstanceOf(JsonResponse::class, $result);
|
|
||||||
static::assertEquals(Response::HTTP_FORBIDDEN, $result->getStatusCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSupports(): void
|
|
||||||
{
|
|
||||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
|
||||||
|
|
||||||
$auth = new CallbackClientAuthenticator($errorResponseFactory);
|
|
||||||
$result = $auth->supports(new Request([], [CallbackClientAuthenticator::AUTH_FIELD => '123']));
|
|
||||||
|
|
||||||
static::assertTrue($result);
|
|
||||||
|
|
||||||
$result = $auth->supports(new Request([CallbackClientAuthenticator::AUTH_FIELD => '123']));
|
|
||||||
|
|
||||||
static::assertTrue($result);
|
|
||||||
|
|
||||||
$result = $auth->supports(new Request());
|
|
||||||
|
|
||||||
static::assertFalse($result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAuthenticate(): void
|
|
||||||
{
|
|
||||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
|
||||||
$user = new User();
|
|
||||||
|
|
||||||
$auth = new CallbackClientAuthenticator($errorResponseFactory);
|
|
||||||
$passport = $auth->authenticate(new Request([], [CallbackClientAuthenticator::AUTH_FIELD => '123']));
|
|
||||||
static::assertTrue($passport->hasBadge(UserBadge::class));
|
|
||||||
static::assertEquals(
|
|
||||||
$user->getUserIdentifier(),
|
|
||||||
$passport->getBadge(UserBadge::class)->getUserIdentifier()
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->expectException(AuthenticationException::class);
|
|
||||||
$auth->authenticate(new Request());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testOnAuthenticationSuccess(): void
|
|
||||||
{
|
|
||||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
|
||||||
$request = $this->createMock(Request::class);
|
|
||||||
$token = $this->createMock(TokenInterface::class);
|
|
||||||
$auth = new CallbackClientAuthenticator($errorResponseFactory);
|
|
||||||
|
|
||||||
$result = $auth->onAuthenticationSuccess($request, $token, 'key');
|
|
||||||
|
|
||||||
static::assertNull($result);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user