Symfony 4 get authentification with cas and roles via database - symfony

I am having trouble finding any help, examples or tutorials that layout how to use CAS for Authorization but load the roles from a local database in Symfony 4.
I managed to authenticate via CAS using the bundle: prayno. I manage to succesfully get roles from a database via an entity and repository. But the fact is that I did not manage to make the link between the twos.
Here is my security.yaml:
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from- user-providers
providers:
cas:
id: prayno.cas_user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
logout: ~
guard:
authenticators:
- prayno.cas_authenticator
The function under the prayno bundle to get authentification and the roles:
public function loadUserByUsername($username)
{
if ($username) {
$password = '...';
$salt = "";
$roles = ['ROLE_USER'];
return new CasUser($username, $password, $salt, $roles);
}
throw new UsernameNotFoundException(
sprintf('Username "%s" does not exist.', $username)
);
}
From there, I tried to get my roles from the database using the controller I created for this occasion:
<?php
namespace App\Controller;
use App\Entity\FscDroitsBundle;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class RightsController extends AbstractController
{
/**
* #Route("/rights", name="rights")
*/
public function attribute_rights($netid)
{
$entities = $this->em->getDoctrine()->getRepository(FscDroitsBundle::class)->findRights($netid);
$rights_array = array('ROLE_USER');
foreach ($entities as $data) {
array_push($rights_array, $data->getBundle());
}
return $rights_array;
}
But, until now, I did not find any way to use this controller in the bundle, something like:
$rights = new RightsController();
$roles = $rights->attribute_rights($username);
instead of:
$roles = ['ROLE_USER'];
in my loadbyUsername function.
The problem seems to come from this line:
$entities = $this->getDoctrine()->getRepository(FscDroitsBundle::class)->findRights($netid);
The error is: Call to a member function has() on null
How is it that the controller can not access the repository in the bundle meanwhile it access it without any problem on a view ?

Related

Symfony 5.4 LDAP and User-Entity Password mixed

Is ist possible to configure user authentification for Symfony 5.4 using either User/Password stored in the User entity oder LDAP depending on a boolean field or the password being null in the User entity?
I need to create some users that have to log on but are not contained in the customers LDAP structure. LDAP is more a comfort thing (single credentials for all apps) here than a security one (no one may logon if not defined in LDAP).
Perhaps I can get around programming the security things from the scatch and just combine two different providers.
Meanwhile I solved it and it was quite easy by using the "normal" password authenticator and modifying a bit of code. The strategy is:
Check if its an LDAP user. If not, use password authentication
Search the user in the LDAP directory
Bail out if not found
Bail out if not unique
Check credentials
The steps I took:
I added a boolean field to the entity USER called ldap_flag
I added variables to .env to specify the LDAP parameters
I modified Security/LoginFormAuthenticator:checkCredentials like this:
if ($user->getLDAPFlag()) {
if ($conn = ldap_connect($_ENV['LDAP_HOST'])) {
ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, $_ENV['LDAP_PROTOCOL_VERSION']);
ldap_set_option($conn, LDAP_OPT_REFERRALS, 0);
if ($_ENV['LDAP_CERT_CHECK'] == 0)
ldap_set_option($conn, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER);
$dn = $_ENV['LDAP_BIND_DN'];
$pw = $_ENV['LDAP_BIND_PW'];
if (ldap_bind($conn, $dn, $pw)) {
// Search user
$res = ldap_search($conn, $_ENV['LDAP_SEARCH_DN'], "(&(uid=" . $user->getUserName() . ")(objectClass=inetOrgPerson))", array('dn'));
$entries = ldap_get_entries($conn, $res);
if ($entries["count"] == 1)
return ldap_bind($conn, $entries[0]['dn'], $credentials['password']);
else if ($entries["count"] > 0)
throw new CustomUserMessageAuthenticationException('Benutzer im LDAP nicht eindeutig!');
else
throw new CustomUserMessageAuthenticationException('Benutzer auf dem LDAP Server nicht gefunden!');
} else
// cannot bind
throw new CustomUserMessageAuthenticationException('Kann nicht an LDAP-Server binden!');
ldap_unind($conn);
} else {
// no LDAP Connection
throw new CustomUserMessageAuthenticationException('Keine Verbindung zum LDAP-Server');
}
} else
// internal password-check
return $this->passwordEncoder->isPasswordValid($user, $credentials['password']);
}
The error messages are in German but it should be easy to adapt them to an other language as they explain within their context.
I have found another solution, which makes use of Symfony's services. But it is not a one liner. One has to define several configurations, override some services and create two custom classes.
But this advices should be relatively complete.
# config/packages/security.yaml
security:
enable_authenticator_manager: true
providers:
all_users:
chain:
providers: [ldap_users, local_users]
local_users:
entity:
class: App\Entity\User
property: username
ldap_users:
# in services.yml Symfony's provider is overwritten with
# App\Security\LdapUserProvider
ldap:
service: Symfony\Component\Ldap\Ldap # see services.yml
base_dn: '%env(LDAP_BASE_DN)%'
search_dn: '%env(LDAP_SEARCH_DN)%'
search_password: '%env(LDAP_SEARCH_PASSWORD)%'
default_roles: ROLE_USER
uid_key: '%env(LDAP_UID_KEY)%'
firewalls:
main:
pattern: ^/
lazy: true
provider: all_users
form_login_ldap:
check_path: app_login
login_path: app_login
service: Symfony\Component\Ldap\Ldap # see services.yml
dn_string: '%env(LDAP_BASE_DN)%'
search_dn: '%env(LDAP_SEARCH_DN)%'
search_password: '%env(LDAP_SEARCH_PASSWORD)%'
query_string: 'sAMAccountName={username}'
# config/services.yaml
services:
Symfony\Component\Ldap\Ldap:
arguments: ['#Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
tags:
- ldap
Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
arguments:
- host: '%env(LDAP_HOST)%'
port: 389
encryption: none
options: { protocol_version: 3, referrals: false, network_timeout: 5 }
# overwrite symfony's LdapUserProvider so that a User entity is used
# instead of the default user class of Symfony.
security.user.provider.ldap:
class: App\Security\LdapUserProvider
arguments: [~, ~, ~, ~, ~, ~, ~, ~, ~]
App\Security\AppCredentialsCheckListener:
decorates: 'security.listener.form_login_ldap.main'
arguments:
$checkLdapCredentialsListener: '#.inner'
$checkCredentialsListener: '#security.listener.check_authenticator_credentials'
// src/Security/LdapUserProvider.php
namespace App\Security;
use App\Entity\User;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Ldap\Entry;
use Symfony\Component\Ldap\LdapInterface;
use Symfony\Component\Ldap\Security\LdapUserProvider as BaseLdapUserProvider;
/**
* This service is responsible for adding a user entity to the local database.
*/
class LdapUserProvider extends BaseLdapUserProvider
{
private EntityManagerInterface $entityManager;
private UserRepository $userRepo;
public function __construct(
LdapInterface $ldap,
string $baseDn,
string $searchDn,
string $searchPassword,
array $defaultRoles,
string $uidKey,
string $filter,
?string $passwordAttribute,
?array $extraFields,
EntityManagerInterface $entityManager,
UserRepository $userRepo
) {
parent::__construct($ldap, $baseDn, $searchDn, $searchPassword, $defaultRoles, $uidKey, $filter, $passwordAttribute, $extraFields);
$this->entityManager = $entityManager;
$this->userRepo = $userRepo;
}
protected function loadUser(string $username, Entry $entry)
{
$ldapUser = parent::loadUser($username, $entry);
$user = $this->userRepo->findOneBy(['username' => $ldapUser->getUsername()]);
$flush = false;
if (!$user) {
$user = new User();
$user->setUsername($ldapUser->getUsername());
$this->entityManager->persist($user);
$this->entityManager->flush();
}
return $user;
}
}
// src/Security/AppCredentialsCheckListener.php
namespace App\Security;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Ldap\Security\CheckLdapCredentialsListener;
use Symfony\Component\Ldap\Security\LdapBadge;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
use Symfony\Component\Security\Http\EventListener\CheckCredentialsListener;
/**
* This event listener is responsible for checking the password.
* First the LDAP password is checked and as a fallback the local
* password is checked
*/
class AppCredentialsCheckListener implements EventSubscriberInterface
{
private CheckLdapCredentialsListener $checkLdapCredentialsListener;
private CheckCredentialsListener $checkCredentialsListener;
public function __construct(
CheckLdapCredentialsListener $checkLdapCredentialsListener,
CheckCredentialsListener $checkCredentialsListener
) {
$this->checkLdapCredentialsListener = $checkLdapCredentialsListener;
$this->checkCredentialsListener = $checkCredentialsListener;
}
public static function getSubscribedEvents(): array
{
// priority must be higher than the priority of the Symfony listeners
return [CheckPassportEvent::class => ['onCheckPassport', 999]];
}
public function onCheckPassport(CheckPassportEvent $event)
{
try {
// Check ldap password
$this->checkLdapCredentialsListener->onCheckPassport($event);
} catch (BadCredentialsException $e) {
// Fallback to local entity password
$this->checkCredentialsListener->checkPassport($event);
// We have to mark the ldap badge as resolved. Otherwise an exception will be thrown.
/** #var LdapBadge $ldapBadge */
$ldapBadge = $event->getPassport()->getBadge(LdapBadge::class);
$ldapBadge->markResolved();
}
}
}
I have added some comments to the config and the code, which should make clear how it is achieved. I hope it helps anyone.

Symfony PHPUnit tests don't authenticate user

I have a Symfony 4.4 project. Login, authentication, and authorization work fine on web.
To simulate authentication in unit tests, I'm using Symfony's example.
...but that's not working. The user is not authenticated in the unit test. I get an Unauthorized with error message "Full authentication is required to access this resource."
My test:
namespace App\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
class DefaultControllerTest extends WebTestCase
{
private $client = null;
public function setUp()
{
$this->client = static::createClient();
}
public function testJsonUserEndpoint()
{
$this->logIn();
$crawler = $this->client->request('GET', '/json/user');
$this->assertNotContains('invalid_credentials', $this->client->getResponse()->getContent());
}
private function logIn()
{
$user = self::$container->get(EntityManagerInterface::class)->getRepository(User::class)->findOneByMail('test106#test.com');
$session = $this->client->getContainer()->get('session');
$firewallName = 'main';
$firewallContext = 'main';
$token = new PostAuthenticationGuardToken($user, $firewallName, ['ROLE_USER']);
$session->set('_security_'.$firewallContext, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
}
My firewall:
main:
anonymous:
secret: '%env(APP_SECRET)%'
remember_me:
always_remember_me: true
secret: '%env(APP_SECRET)%'
provider: session_user_provider
guard:
authenticators:
- App\Security\Authenticator\LoginAuthenticator
- App\Security\Authenticator\MobileBridgeAuthenticator
- App\Security\Authenticator\BearerTokenAuthenticator
- App\Security\Authenticator\HashAuthenticator
- App\Security\Authenticator\ClientAuthenticator
entry_point: App\Security\Authenticator\LoginAuthenticator
logout:
path: execute_logout
target: render_login
Unit test failure:
1) App\Tests\Controller\DefaultControllerTest::testJsonUserEndpoint
Failed asserting that '{"status":"invalid_credentials","errors":["Invalid Credentials"],"debug":"Full authentication is required to access this resource.","error":"Unauthorized"}' does not contain "invalid_credentials".
How can I authenticate a user in my unit tests without using the login form?
The problem was that I don't store roles in the database with the user -- they're added in my authenticators -- and passing the roles to PostAuthenticationGuardToken wasn't enough. I also had to add them to the user in the token:
$user->setRoles(['ROLE_USER']);
$token = new PostAuthenticationGuardToken($session_user, $firewallName, ['ROLE_USER']);
Actually, it didn't even matter what's in the Token's roles as long as it's an array:
$user->setRoles(['ROLE_USER']);
$token = new PostAuthenticationGuardToken($session_user, $firewallName, []);

How to implement Symfony 5 Authentication without Doctrine?

Am in the process of rewriting an existing PHP project to Symfony 5.3. I want to upgrade its authentication system to Symfony's. Only issue: Doctrine is not an option in this project.
How can I use Symfony's authentication (possibly together with the new Authenticator-based Security) without invoking Doctrine anywhere?
I know that I must implement a UserLoaderInterface, but the docs use Doctrine so heavily that I cannot figure out how to do it without.
The post I just mentioned is asking something similar, but it still uses Symfony 2 and is thus too outdated.
I have a database that has the necessary User table with the usual columns (ID, eMail, Password, Name, etc.).
To the point:
How can I use Symfony's authentication (possibly together with the new Authenticator-based Security) without Doctrine?
To configurate that is on the the official website and also on this tutorial in SymfonyCast, but basically you can authenticate the user as you want:
See the next example:
Create a file on src\App\Security folder if your configuration is using the default config and create the class TokenAuthenticator, now see the below code, in this case check the class App\Service\ExternalAuthenticator, who will be in charge to get the information from other service or api and the return.
<?php
namespace App\Security;
use App\Example\Student;
use App\Service\ExternalAuthenticator;
use App\DTO\INFORMATIONFROMOTHERSERVICE;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Security;
final class TokenAuthenticator extends AbstractGuardAuthenticator
{
/** #var Security */
private $security;
/** #var ExternalAuthenticator */
private $externalAuthenticator;
/** #var UrlGeneratorInterface */
private $urlGenerator;
public function __construct(
Security $security,
ExternalAuthenticator $externalAuthenticator
) {
$this->security = $security;
$this->externalAuthenticator = $externalAuthenticator;
}
/**
* {#inheritDoc}
*/
public function supports(Request $request)
{
//on this example, this guard must be using if on the request contains the word token
$response = false;
$apiKey = $request->query->get('token');
if (!is_null($apiKey)) {
$response = true;
}
return $response;
}
/**
* {#inheritDoc}
*/
public function getCredentials(Request $request)
{
$apiKey = $request->query->get('token');
// Validate with anything you want, other service or api
/** #var INFORMATIONFROMOTHERSERVICE**/
$dtoToken = $this->externalAuthenticator->validateToken($apiKey, $simulator);
return $dtoToken;
}
/**
* #param INFORMATIONFROMOTHERSERVICE $credentials
* #param UserProviderInterface $userProvider
* #return INFORMATIONFROMOTHERSERVICE |UserInterface|null
*/
public function getUser($credentials, UserProviderInterface $userProvider)
{
return $userProvider;
}
public function checkCredentials($credentials, UserInterface $user)
{
return true;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
return new RedirectResponse($this->urlGenerator->generate('home_incorrect'));
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
{
return new RedirectResponse($request->getPathInfo());
}
public function start(Request $request, AuthenticationException $authException = null)
{
return new RedirectResponse($this->urlGenerator->generate('home_incorrect'));
}
public function supportsRememberMe()
{
// todo
}
}
Now the external service must return App\DTO\INFORMATIONFROMOTHERSERVICE class, but this class must implement the UserInterface, now with this in mind. We need to configurate what guard must be in charge of what routes, see the next example:
security:
encoders:
App\Entity\User:
algorithm: bcrypt
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: email
//You can use a
custom_provider:
id : App\DTO\INFORMATIONFROMOTHERSERVICE
# used to reload user from session & other features (e.g. switch_user)
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
survey:
anonymous: true
pattern: ^/(custom_path)/
// The
provider: custom_provider
guard:
// You can use as many authenticator that you want, but in the node entrypoint, you must choose who must be the default if only is one you could remove the entrypoint node, similar as the main firewall
authenticators:
- App\Security\TokenAuthenticator
- App\Security\OtherAuthenticator
entry_point: App\Security\OtherAuthenticator
main:
anonymous: true
lazy: true
provider: app_user_provider
logout:
path: app_logout
guard:
authenticators:
- App\Security\AppAuthenticator
Also see the next documentation, that will guide you to create the class App\DTO\INFORMATIONFROMOTHERSERVICE.
I hope this answer, help you

Why credentials are null when erase_credentials is false?

Symfony 5.3
security.yaml
security:
...
erase_credentials: false
LoginListener.php
<?php
namespace App\EventListener;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class LoginListener
{
private $passwordHasherFactory;
private $em;
public function __construct(PasswordHasherFactoryInterface $passwordHasherFactory, EntityManagerInterface $em)
{
$this->passwordHasherFactory = $passwordHasherFactory;
$this->em = $em;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
$token = $event->getAuthenticationToken();
// Migrate the user to the new hashing algorithm if is using the legacy one
if ($user->hasLegacyPassword()) {
// Credentials can be retrieved thanks to the false value of
// the erase_credentials parameter in security.yml
$plainPassword = $token->getCredentials();
file_put_contents('darius.txt', 'test'.$plainPassword, FILE_APPEND); // why null?
}
$token->eraseCredentials();
}
}
https://symfony.com/doc/current/reference/configuration/security.html#erase-credentials
If true, the eraseCredentials() method of the user object is called
after authentication.
So probably if false it should not erase? Why it is erasing?
Password is received because login works. I just dissapears at some point.
Update
Question is why credentials are null before calling
$token->eraseCredentials();
Managed to install xdebug and found that when creating token the credentials are not set:
JsonLoginAuthenticator:
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
{
return new UsernamePasswordToken($passport->getUser(), null, $firewallName, $passport->getUser()->getRoles());
}
UsernamePasswordToken:
public function __construct($user, $credentials, string $firewallName, array $roles = [])
{
parent::__construct($roles);
if ('' === $firewallName) {
throw new \InvalidArgumentException('$firewallName must not be empty.');
}
$this->setUser($user);
$this->credentials = $credentials;
$this->firewallName = $firewallName;
parent::setAuthenticated(\count($roles) > 0);
}
So I guess that is the problem - under security - firewall there is such setup:
main:
lazy: true
provider: app_user_provider
logout:
path: logout
target: after_logout
json_login:
check_path: /login
entry_point: App\Security\AuthenticationEntryPoint
So probably I have answered my question why there is no credentials. I am just missing now how do create new password hash for password on login, but that is probably for different question.

authorizationChecker->isGranted in a phpUnit test

I'm currently creating my unit test for my application but it's the first time I do it.
I want to test this function :
/**
* This method search if the user is already in a team for the same tournament than the one passed in argument
* #param User $user
* #param Team $team
* #return bool|Team|mixed
*/
public function isAlreadyApplicant($user, Team $team) {
if (!$user || !$this->authorizationChecker->isGranted("ROLE_USER")) {
return false;
}
foreach ($user->getApplications() as $userTeam) {
/** #var Team $userTeam */
if ($userTeam->getTournament()->getId() === $team->getTournament()->getId()) {
return $userTeam;
}
}
foreach ($user->getTeams() as $userTeam) {
/** #var Team $userTeam */
if ($userTeam->getTournament()->getId() === $team->getTournament()->getId()) {
return $userTeam;
}
}
foreach ($user->getManagedTeam() as $userTeam) {
/** #var Team $userTeam */
if ($userTeam->getTournament()->getId() === $team->getTournament()->getId()) {
return $userTeam;
}
}
return false;
}
As you can see, the first test is to check if the user have the ROLE_USER.
When I try to "log my user", I have this message :
Fatal error: Call to a member function getToken() on null in \vendor\symfony\symfony\src\Symfony\Component\Security\Core\Authorization\AuthorizationChecker.php on line 56
I tried what I found in the Symfony doc but I must miss something. This is my test Class:
class ApplicationCheckerTest extends WebTestCase
{
protected $client = null;
public function setUp() {
$this->client = static::createClient();
/** #var User $user */
$user = $this->client->getContainer()->get('doctrine')->getManager()->getRepository('MGDUserBundle:User')->findOneBy(array("email" => 'Player11.Player11#test.com'));
$this->loginUser("main", $user);
}
protected function loginUser($firewallName, UserInterface $user, array $options = array(), array $server = array())
{
$this->client = static::createClient();
$token = new UsernamePasswordToken($user, null, $firewallName, $user->getRoles());
static::$kernel->getContainer()->get('security.token_storage')->setToken($token);
$session = $this->client->getContainer()->get('session');
$session->set('_security_'.$firewallName, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
public function testIsAlreadyApplicantIsNotConnected()
{
$user = new User();
$team = new Team();
$router = $this->createMock(Router::class);
$authorizationChecker = $this->createMock(AuthorizationChecker::class);
$applicationChecker = new ApplicationChecker($router, $authorizationChecker);
$applicationChecker->isAlreadyApplicant($user, $team);
}
}
And my security.yml looks like :
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
provider: main
form_login:
login_path: fos_user_security_login
check_path: fos_user_security_check
logout:
path: fos_user_security_logout
target: /
remember_me:
secret: '%secret%'
I try to connect a user I created with fixtures.
I'm not sure about the way I try to do it, maybe I'm on the wrong path, don't hesitate to correct me if I'm wrong!
For information, I'm in Symfony 3.2.13
Have a good day
The WebTestCase and the example from the Symfony documentation that you're using should be used for a functional test of your controller.
The way you have set up your authentication for the client is correct. But you are not using that client to make a request to the bootstrapped Symfony kernel in your test case. You are just making a simple unit test on a manually created instance of your service, which is fine.
You can simply use the PHPUnit\Framework\TestCase for that.
It is possible to use the WebTestCase to test your service and overwrite the TokenStorage which is used in the AuthorizationChecker in the kernel container instead of the client container, and then also fetch your service from the kernel container instead of instantiating it yourself. But I don't see much benefit in it. There is no need to test the Symfony component (if isGranted is working). That is in the scope of the Symfony project and most likely already covered there.
Your error
The reason for your error is, that a final method can't be mocked. As a workaround you can set the dependency in your ApplicationChecker constructor to AuthorizationCheckerInterface and then create a mock from the interface in your test.
$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
$authorizationChecker->method('isGranted')->willReturn(true);

Resources