Skip to content

Instantly share code, notes, and snippets.

@aertmann
Last active August 28, 2018 13:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aertmann/f92aa09c71c96ad92eb1e3e96ea9e1a3 to your computer and use it in GitHub Desktop.
Save aertmann/f92aa09c71c96ad92eb1e3e96ea9e1a3 to your computer and use it in GitHub Desktop.
Multi-site access restriction with Neos CMS
Neos:
Flow:
security:
authentication:
providers:
NeosBackendProvider:
provider: 'Acme\Package\Security\Authentication\Provider\SiteAwarePersistedUsernamePasswordProvider'
<?php
namespace Acme\Package\Security\Authentication\Provider;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\EntityNotFoundException;
use TYPO3\Flow\Annotations as Flow;
use TYPO3\Flow\Reflection\ObjectAccess;
use TYPO3\Flow\Security\Authentication\AuthenticationManagerInterface;
use TYPO3\Flow\Security\Authentication\Provider\PersistedUsernamePasswordProvider;
use TYPO3\Flow\Security\Authentication\TokenInterface;
use TYPO3\Flow\Security\Policy\PolicyService;
use TYPO3\Neos\Domain\Repository\DomainRepository;
use TYPO3\Neos\Domain\Repository\SiteRepository;
/**
* A custom site aware authentication provider extending the existing persisted username password provider
*/
class SiteAwarePersistedUsernamePasswordProvider extends PersistedUsernamePasswordProvider
{
/**
* @Flow\Inject
* @var DomainRepository
*/
protected $domainRepository;
/**
* @Flow\Inject
* @var SiteRepository
*/
protected $siteRepository;
/**
* @Flow\Inject
* @var AuthenticationManagerInterface
*/
protected $authenticationManager;
/**
* @Flow\Inject
* @var PolicyService
*/
protected $policyService;
/**
* Doctrine's Entity Manager
*
* @Flow\Inject
* @var ObjectManager
*/
protected $entityManager;
/**
* Checks if a user has access to a site by enabling entity privileges and checking if user has access to current site
*
* @param TokenInterface $authenticationToken The token to be authenticated
* @return void
*/
public function authenticate(TokenInterface $authenticationToken)
{
parent::authenticate($authenticationToken);
if ($authenticationToken->getAuthenticationStatus() !== TokenInterface::AUTHENTICATION_SUCCESSFUL) {
return;
}
// Force set isAuthenticated to true on authentication manager to update roles needed for entity privileges
ObjectAccess::setProperty($this->authenticationManager, 'isAuthenticated', true, true);
$domain = $this->domainRepository->findOneByActiveRequest();
if (!$domain) {
if (!array_key_exists('Neos.Neos:Administrator', $this->securityContext->getRoles())) {
$this->rollback($authenticationToken);
}
return;
}
// Check if user can access site and ensure it's not already loaded
$this->entityManager->clear('TYPO3\Neos\Domain\Model\Site');
$site = $this->siteRepository->findByIdentifier(ObjectAccess::getProperty($domain->getSite(), 'Persistence_Object_Identifier', true));
if (!$site) {
$this->rollback($authenticationToken);
}
}
/**
* @param TokenInterface $authenticationToken
* @return void
*/
protected function rollback(TokenInterface $authenticationToken)
{
$authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS);
ObjectAccess::setProperty($this->authenticationManager, 'isAuthenticated', false, true);
$this->policyService->reset();
$this->securityContext->refreshRoles();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment