I am building a site using Symfony2 and it will be a white-label type of site, where multiple domains map to the same server. So coolsite.customer1.com and aservice.customer2.com would map to the same site, but would need to appear different to the end user. I already solved for the domains, and loading the unique configurations as a service.
With the FOS UserBundle setup and running with a custom user (that has the domain_id stored in it), registration, login, etc works fine except that users from domain1 can login to domain2 also. This is expected in the FOS UserBundle. I need to make modifications to the bundle so that it only will authenticate users on the domain they are assigned to.
I have created a userProvider that extends the original userProvider in FOS and have overridden the loadUserByUsername method to also check the domain. See below:
use FOS\UserBundle\Security\UserProvider as FOSProvider;
use Symfony\Component\DependencyInjection\ContainerInterface;
use FOS\UserBundle\Model\UserManagerInterface;
use Me\CoreBundle\Models\Core;
class UserProvider extends FOSProvider {
/**
*
* @var ContainerInterface
*/
protected $container;
public function __construct(UserManagerInterface $userManager, ContainerInterface $container) {
parent::__construct($userManager);
$this->container = $container;
}
/**
* {@inheritDoc}
*/
public function loadUserByUsername($username)
{
$core = $this->container->get('me_core');
/* @var $core Core */
$user = $this->findUserBy(array(
'username'=>$username,
'domain_id'=>$core->getDomainMap()->getId(),
));
if (!$user) {
throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
}
return $user;
}
public function findUserBy(array $criteria) {
return $this->userManager->findUserBy($criteria);
}
}
I have configured the service with the following.
services:
me.security.authentication.userprovider:
class: Me\UserBundle\Security\UserProvider
arguments:
- @fos_user.user_manager
- @service_container
My security.yml looks like this:
security:
providers:
me.security.authentication.userprovider:
id: fos_user.user_provider.username
encoders:
FOS\UserBundle\Model\UserInterface: sha512
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
logout: true
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/_wdt, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/public, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
- { path: ^/, role: ROLE_USER }
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
What happens when I try to access the site is an exception. "ServiceNotFoundException: The service "security.authentication.manager" has a dependency on a non-existent service "security.user.provider.concrete.fos_userbundle"."
I based my modifications on This Cookbook Recipe
Any ideas? I am thoroughly stumped on this.
I was able to get it to work. Turns out I needed to make the "id" the same as the name of the service I was using. The commented lines are the originals that came with the bundle.
security:
providers:
me.security.authentication.userprovider:
id: me.security.authentication.userprovider
#fos_userbundle:
#id: fos_user.user_provider.username
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With