I'm working in symfony with FosUser and FosAuthServer. I have a front web site who access to an API by Oauth2. On the front web site, if the user is not logon, redirect him to the oauth serveur and after the user is login, redirect him to the font web site with an oauth2 token.
It's work well, but I need this : if user is find in the database (my user provider), longin him if the user is not find in the database, I search him in LDAP and I login him manually.
To do this, I use the AuthenticationFailureHandler to find the user in the LDAP. After find him, I create a User Entity and dispatch envent FOSUserEvents::SECURITY_IMPLICIT_LOGIN, but I don't know who can I create a token and redirect to the front web site.
security.yml
security:
encoders:
AppBundle\Entity\User: sha512
Symfony\Component\Security\Core\User\User: plaintext
providers:
api:
id: fos_user.user_provider.username_email
admin:
memory:
users:
admin: { password: password}
firewalls:
doc:
pattern: ^/api/doc
anonymous: true
oauth_token:
pattern: ^/oauth/v2/token
security: false
oauth_authorize:
pattern: ^/oauth/v2/auth
guard:
authenticators:
- app.security.login_form_authenticator
form_login:
provider: api
csrf_token_generator: security.csrf.token_manager
login_path: fos_user_security_login
check_path: fos_user_security_check
failure_handler: app.authentification_failure_handler
logout:
path: fos_user_security_logout
target: fos_user_security_login
anonymous: true
admin:
pattern: ^/admin
http_basic:
realm: 'Secured Area'
provider: admin
anonymous: false
api:
pattern: ^/api
fos_oauth: true
stateless: true
anonymous: false
access_control:
- { path: ^/oauth/v2/auth, roles: [ IS_AUTHENTICATED_ANONYMOUSLY ] }
- { path: ^/api/doc, roles: [ IS_AUTHENTICATED_ANONYMOUSLY ] }
- { path: ^/admin, roles: [ IS_AUTHENTICATED_FULLY ] }
- { path: ^/, roles: [ ROLE_USER ] }
Service.yml
app.authentification_failure_handler:
public: false
class: AppBundle\Handler\AuthenticationFailureHandler
arguments:
- '@utilities.active_directory.ageo'
- '@doctrine.orm.entity_manager'
- '@fos_user.user_manager'
- '@security.token_storage'
- '@debug.event_dispatcher'
- '@router'
- '@http_kernel'
- '@security.http_utils'
AuthentificationFaillureHandler.php
<?php
namespace AppBundle\Handler;
use AppBundle\Entity\Assure;
use AppBundle\Entity\BrokerStructur;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use FOS\OAuthServerBundle\Model\AuthCodeManager;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\HttpUtils;
class AuthenticationFailureHandler extends DefaultAuthenticationFailureHandler
{
// private $cafeteriaEntityManager;
private $router;
/**
* @var \Ageo\UtilitiesBundle\ActiveDirectory\Ageo Connection au LDAP Ageo
*/
private $ldap;
/**
* @var $entityManagerSql Manager des entitées de la base mysql
*/
private $entityManagerSql;
/**
* @var UserManager Manager des utilisateurs (FosUserBundle)
*/
private $userManager;
/**
* @var EventDispatcher
*/
private $eventDispatcher;
/**
* @var TokenStorage
*/
private $tokenStorage;
public function __construct(\Ageo\UtilitiesBundle\ActiveDirectory\Ageo $ldap, EntityManager $entityManagerSql, UserManager $userManager,
TokenStorage $tokenStorage, \Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher $eventDispatcher,
RouterInterface $router, HttpKernelInterface $httpKernel, HttpUtils $httpUtils)
{
$this->ldap = $ldap;
$this->router = $router;
$this->entityManagerSql = $entityManagerSql;
$this->userManager = $userManager;
$this->tokenStorage = $tokenStorage;
$this->eventDispatcher = $eventDispatcher;
parent::__construct($httpKernel, $httpUtils, array(), null);
}
/**
* Si l'utilisateur n'est pas présent dans la base de données local, on le cherche dans l'Active directory pour le logguer
* On vérifie ensuite s'il existe dans la base de donné local. S'il existe, on le charge et on le met à jour, sinon, on le crée.
* @param Request $request
* @param AuthenticationException $exception
* @return RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$username = trim($request->request->get('_username'));
$password = trim($request->request->get('_password'));
/*
* Manupulation to find the user in LDAP => $userAd
*/
$loaclUser = $this->userManager->createUser();
$loaclUser
->setEnabled(true)
->setUsername($username)
->setPlainPassword($password)
->setEmail($userAd->hasAttribute('mail') ? $userAd->getAttribute('mail')[0] : null )
$this->userManager->updateUser($loaclUser);
$this->eventDispatcher->dispatch(FOSUserEvents::SECURITY_IMPLICIT_LOGIN, new UserEvent($loaclUser, $request));
//$this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($loaclUser, $request, $response));
// I need to login my user on authServeur
// I have test this, but it's not working
if ($this->session->has('_security.oauth_authorize.target_path'))
{
parse_str(parse_url($this->session->get('_security.oauth_authorize.target_path'), PHP_URL_QUERY), $target_path);
$url = $this->session->get('_security.oauth_authorize.target_path');
}
$response = new RedirectResponse($url);
return $response;
}
}
Anyone say who can I do the same proccess of the login_check ?
I never done it but this seems to be the use case of the chain provider
security:
providers:
chain_provider:
chain:
providers: [api, admin, ldap_provider]