I'm using Scheb's two factor bundle in a Symfony3 project and I'd like to handle the exclude_pattern
parameter differently than it does, but I don't know how.
Normally, exclude_pattern
is used to exclude an unauthenticated route from the two-factor authentication, like debug pages or static content:
# config/config.yml
scheb_two_factor:
...
exclude_pattern: ^/(_(profiler|wdt)|css|images|js)/
its behavior being implemented like this:
/* vendor/scheb/two-factor-bundle/Security/TwoFactor/EventListener/RequestListener.php */
public function onCoreRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
// Exclude path
if ($this->excludePattern !== null && preg_match('#'.$this->excludePattern.'#', $request->getPathInfo())) {
return;
}
...
}
I'd like to handle exclude_pattern
also for authenticated routes, so that I can skip two-factor authentication when I call them. For authenticated I mean within access_control
section under security.yml
, like this:
# app/config/security.yml
security:
...
access_control:
- { path: ^/test, role: ROLE_USER }
Right now, if I add an authenticated route under exclude_pattern, all I get is a AccessDeniedException, probably because the bundle requires that the access_decision_manager
parameter to be set as strategy: unanimous
.
The purpose is long to tell and English is not my native language, but if you really need to know it I can try to explain.
I tagged the question with both symfony3 and symfony2 because I'm using Symfony 3.0 but I'm pretty sure it's identical in Symfony 2.8.
I found a solution by overriding the Voter class from the bundle:
// AppBundle/Security/TwoFactor/Voter.php
namespace AppBundle\Security\TwoFactor;
use Scheb\TwoFactorBundle\Security\TwoFactor\Session\SessionFlagManager;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class Voter extends \Scheb\TwoFactorBundle\Security\TwoFactor\Voter
{
/**
* @var string
*/
protected $excludePattern;
/**
* Voter constructor.
* @param SessionFlagManager $sessionFlagManager
* @param array $providers
* @param $excludePattern
*/
public function __construct(SessionFlagManager $sessionFlagManager, array $providers, $excludePattern)
{
parent::__construct($sessionFlagManager, $providers);
$this->excludePattern = $excludePattern;
}
/**
* @param TokenInterface $token
* @param mixed $object
* @param array $attributes
*
* @return mixed result
*/
public function vote(TokenInterface $token, $object, array $attributes)
{
if ($this->excludePattern !== null && preg_match('#'.$this->excludePattern.'#', $object->getPathInfo()))
{
return true;
}
parent::vote($token, $object, $attributes);
}
}
# app/config/services.yml
services:
...
scheb_two_factor.security_voter:
class: 'AppBundle\Security\TwoFactor\Voter'
arguments:
- '@scheb_two_factor.session_flag_manager'
- ~
- '%scheb_two_factor.exclude_pattern%'
This way, whenever the GetResponseEvent is triggered, the right Voter is invoked which votes true
if the exclude_pattern
matches the path.