Symfony 2 custom authentication not using correct provider - php

I'm using FOSRestBundle to create a REST API. For authentication, I'm using a header, which is sent with every request. It's very similar to this cookbook entry.
The listener works fine. Once it calls the following line, I don't see any of my debug or error log entries, it just throws an AuthenticationError exception: $returnValue = $this->authenticationManager->authenticate($token);
I suspect the provider being called is main and not the one I added named api.
security.yml is the only config file that really has much deviation from the cookbook entry:
security:
encoders:
Keobi\ModelBundle\Entity\User:
algorithm: sha512
iterations: 5000
encode_as_base64: true
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
main:
entity: { class: KeobiModelBundle:User, property: email }
api:
entity: { class: KeobiModelBundle:Api, property: key }
factories:
- "%kernel.root_dir%/../src/Keobi/SecurityBundle/Resources/config/secrity_factories.yml"
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/security/login$
security: false
api: # <- this is the firewall for my custom auth
pattern: ^/api/
#security: false
api: true
provider: api
secured_area:
pattern: ^/(keobi|customer|security)/.*$
form_login:
check_path: /security/login_check
login_path: /security/login
success_handler: keobi_security.handler.authentication
failure_handler: keobi_security.handler.authentication
default_target_path: /
target_path_parameter: _target_path
logout:
path: /security/logout
target: /security/login
handlers: [keobi_security.handler.authentication]
switch_user: { role: ROLE_ADMIN }
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_ADMIN }
Here is my ApiListener.php file:
<?php
namespace Keobi\SecurityBundle\Listener;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Keobi\SecurityBundle\Token\ApiToken;
use Symfony\Bridge\Monolog\Logger;
class ApiListener implements ListenerInterface
{
protected $securityContext;
protected $authenticationManager;
protected $logger;
protected $kernel;
const AUTH_HEADER = 'x-keobi-authenticate';
const AUTH_PATTERN = '/^Key="(?P<key>\w{40})", Hash="(?P<hash>\w+)", Created="(?P<created>\d+)"$/';
const SIGN_HEADER = 'x-keobi-signature';
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, Logger $logger, \AppKernel $kernel)
{
$this->securityContext = $securityContext;
$this->authenticationManager = $authenticationManager;
$this->logger = $logger;
$this->kernel = $kernel;
}
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
$kernel = $event->getKernel();
if ($this->kernel->isDebug() && $request->query->has('_apikey') && $request->query->has('_apisecret') && $request->query->has('_ipaddress'))
{
$this->logger->debug('Debug key and secret used.');
$token = new ApiToken();
$created = time();
$hash = hash('sha256', $request->query->get('_apikey') . $request->query->get('_apisecret') . strval($created));
$token->key = $request->query->get('_apikey');
$token->created = $created;
$token->hash = $hash;
$token->ipaddress = $request->query->get('_ipaddress');
}
elseif ($request->headers->has(self::AUTH_HEADER))
{
if (preg_match(self::AUTH_PATTERN, $request->headers->get(self::AUTH_HEADER), $matches))
{
$token = new ApiToken();
$token->key = $matches['key'];
$token->created = $matches['created'];
$token->hash = $matches['hash'];
$token->ipaddress = $request->getClientIp();
}
}
if (isset($token))
{
$this->logger->debug($request->headers->get(self::AUTH_HEADER));
try
{
$this->logger->debug(get_class($this->authenticationManager));
$returnValue = $this->authenticationManager->authenticate($token);
if ($returnValue instanceof TokenInterface)
return $this->securityContext->setToken($returnValue);
elseif ($returnValue instanceof Response)
return $event->setResponse($returnValue);
}
catch (AuthenticationException $e)
{
$this->logger->err('Server failed to authenticate');
}
}
# could not authenticate
$response = new Response();
$response->setStatusCode(403);
$response->setContent('Could not be authenticated.');
$event->setResponse($response);
}
}
Since I posted the listener and the listener is what is generating log entries, these are the log entries that happen when attempting authentication:
2012-07-07 21:47:17 [2fiespfh-4b5a19dd] app.DEBUG: Key="0123456789012345678901234567890123456789", Hash="05707425769f01a82e2eee0b85018feeb6b96579f376f4632782b6b61c83b1fe", Created="1341655731"
2012-07-07 21:47:17 [2fiespfh-4b5a19dd] app.DEBUG: Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager
2012-07-07 21:47:17 [2fiespfh-4b5a19dd] app.ERROR: Server failed to authenticate

Looks like this was ENTIRELY my fault. The reason why it was throwing ProviderNotFoundException was because my supports method in the ApiProvider was checking for the wrong class.

Related

LoginFormAuthenticator::getUser()" method must return a UserInterface

In an attempt to refactor entities from Class Table Inheritance to separate user type classes I've run into this:
The "App\Security\LoginFormAuthenticator::getUser()" method must
return a UserInterface. You returned "array".
From the docs I configured a chain of user providers. I'm at a loss. For a custom user provider I've found Symfony's ChainUserProvider but integrating it into the process is not at all clear. security.yaml doesn't like including it either in firewalls.main.provider or anywhere in providers.all_users
Surely there's something else to add, but what and where?
security.yaml:
security:
encoders:
App\Entity\Admin:
algorithm: auto
App\Entity\Representative:
algorithm: auto
App\Entity\Volunteer:
algorithm: auto
role_hierarchy:
ROLE_SUPER_ADMIN: [ROLE_ADMIN]
providers:
# used to reload user from session & other features (e.g. switch_user)
admin_provider:
entity:
class: 'App\Entity\Admin'
property: email
representative_provider:
entity:
class: 'App\Entity\Representative'
property: email
volunteer_provider:
entity:
class: 'App\Entity\Volunteer'
property: email
all_users:
chain:
providers: ['admin_provider', 'representative_provider', 'volunteer_provider']
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
provider: all_users
user_checker: App\Security\UserChecker
anonymous: ~
guard:
authenticators:
- App\Security\LoginFormAuthenticator
logout:
path: app_logout
target: /
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
path: /
access_control:
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
and modified UserChecker:
use App\Entity\Admin;
use App\Entity\Representative;
use App\Entity\Volunteer;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class UserChecker implements UserCheckerInterface
{
public function checkPreAuth(UserInterface $user)
{
if (!$user instanceof Admin && !$user instanceof Representative && !$user instanceof Volunteer) {
return;
}
}
public function checkPostAuth(UserInterface $user)
{
if (!$user instanceof Admin && !$user instanceof Representative && !$user instanceof Volunteer) {
return;
}
...
}
and modified LoginFormAuthenticator:
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
$admin = $this->entityManager->getRepository(Admin::class)->findBy(['email' => $credentials['email']]);
$rep = $this->entityManager->getRepository(Representative::class)->findBy(['email' => $credentials['email']]);
$vol = $this->entityManager->getRepository(Volunteer::class)->findBy(['email' => $credentials['email']]);
$user = $admin ?? $rep ?? $vol ?? null;
if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Credentials could not be found.');
}
return $user;
}
The issue is that the Doctrine Repository method findBy returns an array, so your attempts to get the user here result with an array:
$admin = $this->entityManager->getRepository(Admin::class)->findBy(['email' => $credentials['email']]);
$rep = $this->entityManager->getRepository(Representative::class)->findBy(['email' => $credentials['email']]);
$vol = $this->entityManager->getRepository(Volunteer::class)->findBy(['email' => $credentials['email']]);
$user = $admin ?? $rep ?? $vol ?? null;
Since I assume you only expect one user when searching by email, you can substitute it with findOneBy, which returns an object or null.

Symfony3 and Ajax Authentication

I want members to log in from the frontend and I've defined my authentication handler below and added it as a service which gives me a json response as expected.
<?php
namespace AppBundle\Handler;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Router;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
class AuthenticationHandler implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface
{
protected $router;
//protected $security;
protected $userManager;
protected $service_container;
public function __construct(RouterInterface $router, $userManager, $service_container)
{
$this->router = $router;
//$this->security = $security;
$this->userManager = $userManager;
$this->service_container = $service_container;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token) {
if ($request->isXmlHttpRequest()) {
$result = array('success' => true);
$response = new Response(json_encode($result));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
else {
// Create a flash message with the authentication error message
$request->getSession()->set(SecurityContext::AUTHENTICATION_ERROR, $exception);
$url = $this->router->generate('fos_user_security_login');
return new RedirectResponse($url);
}
return new RedirectResponse($this->router->generate('anag_new'));
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception) {
if ($request->isXmlHttpRequest()) {
$result = array('success' => false, 'message' => $exception->getMessage());
$response = new Response(json_encode($result));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
return new Response();
}
}
However, I am getting same results regardless of whether a user is registered or not. Here is the response
{"success":false,"message":"Bad credentials."}
Here is my security.yml
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin:
pattern: /admin(.*)
context: user
form_login:
provider: fos_userbundle
login_path: /admin/login
use_forward: false
check_path: /admin/login_check
failure_path: null
logout:
path: /admin/logout
target: /admin/login
anonymous: true
main:
pattern: .*
context: user
form_login:
provider: fos_userbundle
login_path: /login
use_forward: false
check_path: fos_user_security_check
failure_path: null
success_handler: authentication_handler
failure_handler: authentication_handler
logout: true
anonymous: true
routing.yml
fos_user_security_check:
path: /login_check
defaults:
_controller: FOSUserBundle:Security:check
fos_user_security_logout:
path: /logout
defaults:
_controller: FOSUserBundle:Security:logout
The esiest way to implement API authentication for me is to implement the brand new Guard Authentication Interface
http://symfony.com/doc/current/cookbook/security/guard-authentication.html
This simple class allows you to define the process, which instantiate, handles and post-processes authentication.
Enabling the service is as easy as
# app/config/security.yml
security:
# ...
firewalls:
# ...
main:
anonymous: ~
logout: ~
guard:
authenticators:
- app.my_authenticator
# if you want, disable storing the user in the session
# stateless: true
# maybe other things, like form_login, remember_me, etc
# ...
You also need a user provide for this
http://symfony.com/doc/current/cookbook/security/custom_provider.html
Using the Guard you can handle any type of custom authentication (bearer, forms, cookies, GET tokens etc)

Function test fails

I'm trying to do functional test for the routes that are behind the firewall. I'm not sure what I'm doing wrong but the test for the route admin/dashboard fails. Any ideas?
<?php
namespace AppBundle\Tests;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
class ApplicationAvailabilityFunctionalTest extends WebTestCase
{
private $client;
public function setUp()
{
$this->client = self::createClient();
}
/**
* #dataProvider urlProvider
*/
public function testPageIsSuccessful($url)
{
$this->client->request('GET', $url);
$this->assertTrue($this->client->getResponse()->isSuccessful());
}
public function urlProvider()
{
$this->logIn();
return array(
array('/'),
array('/admin/login'),
array('/admin/dashboard'),
);
}
public function logIn()
{
$this->client = self::createClient();
$session = $this->client->getContainer()->get('session');
$firewall = 'our_db_provider';
$token = new UsernamePasswordToken('admin', 'admin', $firewall, array('ROLE_ADMIN'));
$session->set('_security_'.$firewall, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
}
//UPDATE
Here's the error I get
1) AppBundle\Tests\ApplicationAvailabilityFunctionalTest::testPageIsSuccessful with data set #2 ('/admin/dashboard')
Failed asserting that false is true.
/Users/me/Projects/cms/src/AppBundle/Tests/ApplicationAvailabilityFunctionalTest.php:27
//UPDATE 2
Here's the dump of $token variable
Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken {#488
-credentials: null
-providerKey: "security"
-user: "admin"
-roles: array:1 [
0 => Symfony\Component\Security\Core\Role\Role {#487
-role: "ROLE_ADMIN"
}
]
-authenticated: true
-attributes: []
}
//UPDATE 3
`security:
encoders:
AppBundle\Entity\Admin\User:
algorithm: bcrypt
providers:
our_db_provider:
entity:
class: AppBundle\Entity\Admin\User
property: username
access_control:
- { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, roles: ROLE_ADMIN }
firewalls:
default:
anonymous: ~
http_basic: ~
form_login:
login_path: /admin/login
check_path: /admin/login_check
csrf_provider: security.csrf.token_manager
logout:
path: /admin/logout
target: /admin/login
provider: our_db_provider
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~`
The route is not public
The failing test is on the /admin/dashboard route that probably is protected by authentication so the server response is not successfully (200 OK) but (403 access denied or 302 redirect)
So you must test your route differently: the route is protected so check for 403 or that redirect to login page
Check the doc about How to Simulate Authentication with a Token in a Functional Test
And test that an authenticated user see correctly the page

Multiple authentication providers in Symfony 2 for a single firewall

I have a Symfony 2.7.6 project with custom Simple Form authentication provider and support for remember me functionality as well as impersonalization feature. Everything works as expected.
However, I want to introduce another authentication provider that will allow requests regardless of session state using two HTTP headers for authentication (e.g. API-Client-Id and API-Client-Token) for third-party applications.
I've created a Simple Pre-Auth authentication provider that validates these header fields and creates authentication token with empty User instance on success.
However, it looks like Symfony is trying to remember those API authentications using session, so I'm getting the following error on the second request: "You cannot refresh a user from the EntityUserProvider that does not contain an identifier. The user object has to be serialized with its own identifier mapped by Doctrine.".
I can set stateless: true flag in my firewall configuration to disable session support, but it will disable it for both auth providers.
SO, how do I preserve existing functionality with my Simple Form authenticator and yet create another layer of authentication to be used for single stateless API requests?
I'm not sure if my approach is conceptually correct. I will gladly accept any suggestions and will provide any relevant information on first request.
Here's my security.yml config:
security:
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: ~
form_login:
login_path: app.login
check_path: app.session.sign_in
username_parameter: username
password_parameter: password
success_handler: app.security.login_handler
failure_handler: app.security.login_handler
require_previous_session: false
logout:
path: app.session.sign_out
invalidate_session: false
success_handler: app.security.logout_success_handler
# Simple form auth provider
simple_form:
authenticator: app.security.authenticator.out_service
# Token provider
simple_preauth:
authenticator: app.security.authenticator.api_client
remember_me:
name: "%app.session.remember_me.name%"
key: "%secret%"
lifetime: 1209600 # 14 days
path: /
domain: ~
always_remember_me: true
switch_user: { role: ROLE_ADMIN }
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/recover-password, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /, roles: IS_AUTHENTICATED_REMEMBERED }
providers:
main:
entity:
class: App\AppBundle\Model\User
property: id
encoders:
App\AppBundle\Model\User: plaintext
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_ACTIVE]
ROLE_API_CLIENT: ~
ROLE_USER: ~
ROLE_ACTIVE: ~
ApiClientAuthenticator.php:
<?php
namespace App\AppBundle\Security;
use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use App\AppBundle\Model\User;
class ApiClientAuthenticator implements SimplePreAuthenticatorInterface
{
/** #var LoggerInterface */
protected $logger;
/** #var array */
protected $clients;
/**
* #param array $clients
*/
public function __construct(array $clients)
{
$this->clients = $clients;
}
public function createToken(Request $request, $providerKey)
{
$clientId = $request->headers->get('Api-Client-Id');
$clientSecret = $request->headers->get('Api-Client-Secret');
if (!$clientId || !$clientSecret) {
return null;
}
return new PreAuthenticatedToken(
'anon.',
[$clientId, $clientSecret],
$providerKey
);
}
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
list ($clientId, $clientSecret) = $token->getCredentials();
$foundClient = null;
foreach ($this->clients as $client) {
if ($client['id'] == $clientId) {
if ($client['secret'] == $clientSecret) {
$foundClient = $client;
break;
}
}
}
if (!$foundClient) {
throw new AuthenticationException;
}
$user = new User;
$user->setApiClient(true);
return new PreAuthenticatedToken(
$user,
$foundClient,
$providerKey,
['ROLE_API_CLIENT']
);
}
public function supportsToken(TokenInterface $token, $providerKey)
{
return ($token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey);
}
}

How to log in User in Session within a Functional Test in Symfony 2.3?

I have read many posts on stackoverflow about this. But most of the methods not useful in Symfony 2.3.
So I have try to log in user manually in test to make some actions in back-end.
Here is my security.yml
security:
...
role_hierarchy:
ROLE_SILVER: [ROLE_BRONZE]
ROLE_GOLD: [ROLE_BRONZE, ROLE_SILVER]
ROLE_PLATINUM: [ROLE_BRONZE, ROLE_SILVER, ROLE_GOLD]
ROLE_ADMIN: [ROLE_BRONZE, ROLE_SILVER, ROLE_GOLD, ROLE_PLATINUM, ROLE_ALLOWED_TO_SWITCH]
providers:
database:
entity: { class: Fox\PersonBundle\Entity\Person, property: username }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/person/login$
security: false
main:
pattern: ^/
provider: database
form_login:
check_path: /person/login-check
login_path: /person/login
default_target_path: /person/view
always_use_default_target_path: true
logout:
path: /person/logout
target: /
anonymous: true
access_control:
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/person/registration, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/person, roles: ROLE_BRONZE }
Here is my test:
class ProfileControllerTest extends WebTestCase
{
public function setUp()
{
$kernel = self::getKernelClass();
self::$kernel = new $kernel('dev', true);
self::$kernel->boot();
}
public function testView()
{
$client = static::createClient();
$person = self::$kernel->getContainer()->get('doctrine')->getRepository('FoxPersonBundle:Person')->findOneByUsername('master');
$token = new UsernamePasswordToken($person, $person->getPassword(), 'main', $person->getRoles());
self::$kernel->getContainer()->get('security.context')->setToken($token);
self::$kernel->getContainer()->get('event_dispatcher')->dispatch(
AuthenticationEvents::AUTHENTICATION_SUCCESS,
new AuthenticationEvent($token));
$crawler = $client->request('GET', '/person/view');
}
And when I run this test, $person = $this->get(security.context)->getToken()->getUser(); method is not working in testing Controller. Say if in controller call $person->getId(); I will have an error Call to a member function getId() on a non-object in... .
So can you tell the properly way to log in user in functional test in Symfony 2.3?
Thanks!
EDIT_1:
If I change Symfony/Component/Security/Http/Firewall/ContextListener.php and comment one string:
if (null === $session || null === $token = $session->get('_security_'.$this->contextKey)) {
// $this->context->setToken(null);
return;
}
all tests going on without errors.
EDIT_2:
This is reference that i have trying to use:
first
second
third
fourth
fifth
sixth
seventh
eighth
nineth
Finaly i solve it! This is example of working code:
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\BrowserKit\Cookie;
class ProfileControllerTest extends WebTestCase
{
protected function createAuthorizedClient()
{
$client = static::createClient();
$container = static::$kernel->getContainer();
$session = $container->get('session');
$person = self::$kernel->getContainer()->get('doctrine')->getRepository('FoxPersonBundle:Person')->findOneByUsername('master');
$token = new UsernamePasswordToken($person, null, 'main', $person->getRoles());
$session->set('_security_main', serialize($token));
$session->save();
$client->getCookieJar()->set(new Cookie($session->getName(), $session->getId()));
return $client;
}
public function testView()
{
$client = $this->createAuthorizedClient();
$crawler = $client->request('GET', '/person/view');
$this->assertEquals(
200,
$client->getResponse()->getStatusCode()
);
}
Hope it helps to save your time and nerves ;)
As an addition to the accepted solution I will show my function to login user in controller.
// <!-- Symfony 2.4 --> //
use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
private function loginUser(UsernamePasswordToken $token, Request $request) {
$this->get('security.context')->setToken($token);
$s = $this->get('session');
$s->set('_security_main', serialize($token)); // `main` is firewall name
$s->save();
$ed = $this->get('event_dispatcher');
$ed->dispatch(
AuthenticationEvents::AUTHENTICATION_SUCCESS,
new AuthenticationEvent($token)
);
$ed->dispatch(
"security.interactive_login",
new InteractiveLoginEvent($request, $token)
);
}

Categories