Security

Screencast

Do you prefer video tutorials? Check out the Symfony Security screencast series.

Symfony's security system is incredibly powerful, but it can also be confusingto set up. Don't worry! In this article, you'll learn how to set up your app'ssecurity system step-by-step:

1) Installation

In applications using Symfony Flex, run this command toinstall the security feature before using it:

  1. $ composer require symfony/security-bundle

2a) Create your User Class

No matter how you will authenticate (e.g. login form or API tokens) or _where_your user data will be stored (database, single sign-on), the next step is always the same:create a "User" class. The easiest way is to use the MakerBundle.

Let's assume that you want to store your user data in the database with Doctrine:

  1. $ php bin/console make:user
  2.  
  3. The name of the security user class (e.g. User) [User]:
  4. > User
  5.  
  6. Do you want to store user data in the database (via Doctrine)? (yes/no) [yes]:
  7. > yes
  8.  
  9. Enter a property name that will be the unique "display" name for the user (e.g.
  10. email, username, uuid [email]
  11. > email
  12.  
  13. Does this app need to hash/check user passwords? (yes/no) [yes]:
  14. > yes
  15.  
  16. created: src/Entity/User.php
  17. created: src/Repository/UserRepository.php
  18. updated: src/Entity/User.php
  19. updated: config/packages/security.yaml

That's it! The command asks several questions so that it can generate exactly whatyou need. The most important is the User.php file itself. The only rule aboutyour User class is that it must implement UserInterface.Feel free to add any other fields or logic you need. If your User class isan entity (like in this example), you can use the make:entity commandto add more fields. Also, make sure to make and run a migration for the new entity:

  1. $ php bin/console make:migration
  2. $ php bin/console doctrine:migrations:migrate

2b) The "User Provider"

In addition to your User class, you also need a "User provider": a class thathelps with a few things, like reloading the User data from the session and someoptional features, like remember me andimpersonation.

Fortunately, the make:user command already configured one for you in yoursecurity.yaml file under the providers key.

If your User class is an entity, you don't need to do anything else. But ifyour class is not an entity, then make:user will also have generated aUserProvider class that you need to finish. Learn more about user providershere: User Providers.

2c) Encoding Passwords

Not all applications have "users" that need passwords. If your users have passwords,you can control how those passwords are encoded in security.yaml. The make:usercommand will pre-configure this for you:

  • YAML
  1. # config/packages/security.yaml
  2. security:
  3. # ...
  4.  
  5. encoders:
  6. # use your user class name here
  7. App\Entity\User:
  8. # Use native password encoder
  9. # This value auto-selects the best possible hashing algorithm
  10. # (i.e. Sodium when available).
  11. algorithm: auto
  • XML
  1. <!-- config/packages/security.xml -->
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <srv:container xmlns="http://symfony.com/schema/dic/security"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xmlns:srv="http://symfony.com/schema/dic/services"
  6. xsi:schemaLocation="http://symfony.com/schema/dic/services
  7. https://symfony.com/schema/dic/services/services-1.0.xsd">
  8.  
  9. <config>
  10. <!-- ... -->
  11.  
  12. <encoder class="App\Entity\User"
  13. algorithm="auto"
  14. cost="12"/>
  15.  
  16. <!-- ... -->
  17. </config>
  18. </srv:container>
  • PHP
  1. // config/packages/security.php
  2. $container->loadFromExtension('security', [
  3. // ...
  4.  
  5. 'encoders' => [
  6. 'App\Entity\User' => [
  7. 'algorithm' => 'auto',
  8. 'cost' => 12,
  9. ]
  10. ],
  11.  
  12. // ...
  13. ]);

Now that Symfony knows how you want to encode the passwords, you can use theUserPasswordEncoderInterface service to do this before saving your users tothe database.

For example, by using DoctrineFixturesBundle, you cancreate dummy database users:

  1. $ php bin/console make:fixtures
  2.  
  3. The class name of the fixtures to create (e.g. AppFixtures):
  4. > UserFixtures

Use this service to encode the passwords:

  1. // src/DataFixtures/UserFixtures.php
  2.  
  3. + use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  4. // ...
  5.  
  6. class UserFixtures extends Fixture
  7. {
  8. + private $passwordEncoder;
  9.  
  10. + public function __construct(UserPasswordEncoderInterface $passwordEncoder)
  11. + {
  12. + $this->passwordEncoder = $passwordEncoder;
  13. + }
  14.  
  15. public function load(ObjectManager $manager)
  16. {
  17. $user = new User();
  18. // ...
  19.  
  20. + $user->setPassword($this->passwordEncoder->encodePassword(
  21. + $user,
  22. + 'the_new_password'
  23. + ));
  24.  
  25. // ...
  26. }
  27. }

You can manually encode a password by running:

  1. $ php bin/console security:encode-password

3a) Authentication & Firewalls

The security system is configured in config/packages/security.yaml. The _most_important section is firewalls:

  • YAML
  1. # config/packages/security.yaml
  2. security:
  3. firewalls:
  4. dev:
  5. pattern: ^/(_(profiler|wdt)|css|images|js)/
  6. security: false
  7. main:
  8. anonymous: ~
  • XML
  1. <!-- config/packages/security.xml -->
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <srv:container xmlns="http://symfony.com/schema/dic/security"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xmlns:srv="http://symfony.com/schema/dic/services"
  6. xsi:schemaLocation="http://symfony.com/schema/dic/services
  7. https://symfony.com/schema/dic/services/services-1.0.xsd">
  8.  
  9. <config>
  10. <firewall name="dev"
  11. pattern="^/(_(profiler|wdt)|css|images|js)/"
  12. security="false"/>
  13.  
  14. <firewall name="main">
  15. <anonymous/>
  16. </firewall>
  17. </config>
  18. </srv:container>
  • PHP
  1. // config/packages/security.php
  2. $container->loadFromExtension('security', [
  3. 'firewalls' => [
  4. 'dev' => [
  5. 'pattern' => '^/(_(profiler|wdt)|css|images|js)/',
  6. 'security' => false,
  7. ),
  8. 'main' => [
  9. 'anonymous' => null,
  10. ],
  11. ],
  12. ]);

A "firewall" is your authentication system: the configuration below it defineshow your users will be able to authenticate (e.g. login form, API token, etc).

Only one firewall is active on each request: Symfony uses the pattern keyto find the first match (you can also match by host or other things).The dev firewall is really a fake firewall: it just makes sure that you don'taccidentally block Symfony's dev tools - which live under URLs like /_profilerand /_wdt.

All real URLs are handled by the main firewall (no pattern key meansit matches all URLs). But this does not mean that every URL requires authentication.Nope, thanks to the anonymous key, this firewall is accessible anonymously.

In fact, if you go to the homepage right now, you will have access and you'll seethat you're "authenticated" as anon.. Don't be fooled by the "Yes" next toAuthenticated. The firewall verified that it does not know your identity, and so,you are anonymous:

_images/anonymous_wdt.png

You'll learn later how to deny access to certain URLs or controllers.

Note

If you do not see the toolbar, install the profiler with:

  1. $ composer require --dev symfony/profiler-pack

Now that we understand our firewall, the next step is to create a way for yourusers to authenticate!

3b) Authenticating your Users

Authentication in Symfony can feel a bit "magic" at first. That's because, insteadof building a route & controller to handle login, you'll activate anauthentication provider: some code that runs automatically before your controlleris called.

Symfony has several built-in authentication providers.If your use-case matches one of these exactly, great! But, in most cases - includinga login form - we recommend building a Guard Authenticator: a class that allowsyou to control every part of the authentication process (see the next section).

Tip

If your application logs users in via a third-party service such as Google,Facebook or Twitter (social login), check out the HWIOAuthBundle communitybundle.

Guard Authenticators

A Guard authenticator is a class that gives you complete control over yourauthentication process. There are many different ways to build an authenticator,so here are a few common use-cases:

4) Denying Access, Roles and other Authorization

Users can now log in to your app using your login form. Great! Now, you need to learnhow to deny access and work with the User object. This is called authorization,and its job is to decide if a user can access some resource (a URL, a model object,a method call, …).

The process of authorization has two different sides:

  • The user receives a specific set of roles when logging in (e.g. ROLE_ADMIN).
  • You add code so that a resource (e.g. URL, controller) requires a specific"attribute" (most commonly a role like ROLE_ADMIN) in order to beaccessed.

Roles

When a user logs in, Symfony calls the getRoles() method on your Userobject to determine which roles this user has. In the User class that wegenerated earlier, the roles are an array that's stored in the database, andevery user is always given at least one role: ROLE_USER:

  1. // src/Entity/User.php
  2. // ...
  3.  
  4. /**
  5. * @ORM\Column(type="json")
  6. */
  7. private $roles = [];
  8.  
  9. public function getRoles(): array
  10. {
  11. $roles = $this->roles;
  12. // guarantee every user at least has ROLE_USER
  13. $roles[] = 'ROLE_USER';
  14.  
  15. return array_unique($roles);
  16. }

This is a nice default, but you can do whatever you want to determine which rolesa user should have. Here are a few guidelines:

  • Every role must start with ROLE_ (otherwise, things won't work as expected)
  • Other than the above rule, a role is just a string and you can invent what youneed (e.g. ROLE_PRODUCT_ADMIN).You'll use these roles next to grant access to specific sections of your site.You can also use a role hierarchy where havingsome roles automatically give you other roles.

Add Code to Deny Access

There are two ways to deny access to something:

Securing URL patterns (access_control)

The most basic way to secure part of your app is to secure an entire URL patternin security.yaml. For example, to require ROLE_ADMIN for all URLs thatstart with /admin, you can:

  • YAML
  1. # config/packages/security.yaml
  2. security:
  3. # ...
  4.  
  5. firewalls:
  6. # ...
  7. main:
  8. # ...
  9.  
  10. access_control:
  11. # require ROLE_ADMIN for /admin*
  12. - { path: '^/admin', roles: ROLE_ADMIN }
  13.  
  14. # the 'path' value can be any valid regular expression
  15. # (this one will match URLs like /api/post/7298 and /api/comment/528491)
  16. - { path: ^/api/(post|comment)/\d+$, roles: ROLE_USER }
  • XML
  1. <!-- config/packages/security.xml -->
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <srv:container xmlns="http://symfony.com/schema/dic/security"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xmlns:srv="http://symfony.com/schema/dic/services"
  6. xsi:schemaLocation="http://symfony.com/schema/dic/services
  7. https://symfony.com/schema/dic/services/services-1.0.xsd">
  8.  
  9. <config>
  10. <!-- ... -->
  11.  
  12. <firewall name="main">
  13. <!-- ... -->
  14. </firewall>
  15.  
  16. <!-- require ROLE_ADMIN for /admin* -->
  17. <rule path="^/admin" role="ROLE_ADMIN"/>
  18.  
  19. <!-- the 'path' value can be any valid regular expression
  20. (this one will match URLs like /api/post/7298 and /api/comment/528491) -->
  21. <rule path="^/api/(post|comment)/\d+$" role="ROLE_USER"/>
  22. </config>
  23. </srv:container>
  • PHP
  1. // config/packages/security.php
  2. $container->loadFromExtension('security', [
  3. // ...
  4.  
  5. 'firewalls' => [
  6. // ...
  7. 'main' => [
  8. // ...
  9. ],
  10. ],
  11. 'access_control' => [
  12. // require ROLE_ADMIN for /admin*
  13. ['path' => '^/admin', 'roles' => 'ROLE_ADMIN'],
  14.  
  15. // the 'path' value can be any valid regular expression
  16. // (this one will match URLs like /api/post/7298 and /api/comment/528491)
  17. ['path' => '^/api/(post|comment)/\d+$', 'roles' => 'ROLE_USER'],
  18. ],
  19. ]);

You can define as many URL patterns as you need - each is a regular expression.BUT, only one will be matched per request: Symfony starts at the top ofthe list and stops when it finds the first match:

  • YAML
  1. # config/packages/security.yaml
  2. security:
  3. # ...
  4.  
  5. access_control:
  6. # matches /admin/users/*
  7. - { path: '^/admin/users', roles: ROLE_SUPER_ADMIN }
  8.  
  9. # matches /admin/* except for anything matching the above rule
  10. - { path: '^/admin', roles: ROLE_ADMIN }
  • XML
  1. <!-- config/packages/security.xml -->
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <srv:container xmlns="http://symfony.com/schema/dic/security"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xmlns:srv="http://symfony.com/schema/dic/services"
  6. xsi:schemaLocation="http://symfony.com/schema/dic/services
  7. https://symfony.com/schema/dic/services/services-1.0.xsd">
  8.  
  9. <config>
  10. <!-- ... -->
  11.  
  12. <rule path="^/admin/users" role="ROLE_SUPER_ADMIN"/>
  13. <rule path="^/admin" role="ROLE_ADMIN"/>
  14. </config>
  15. </srv:container>
  • PHP
  1. // config/packages/security.php
  2. $container->loadFromExtension('security', [
  3. // ...
  4.  
  5. 'access_control' => [
  6. ['path' => '^/admin/users', 'roles' => 'ROLE_SUPER_ADMIN'],
  7. ['path' => '^/admin', 'roles' => 'ROLE_ADMIN'],
  8. ],
  9. ]);

Prepending the path with ^ means that only URLs beginning with thepattern are matched. For example, a path of /admin (without the ^)would match /admin/foo but would also match URLs like /foo/admin.

Each accesscontrol can also match on IP address, hostname and HTTP methods.It can also be used to redirect a user to the https version of a URL pattern.See [_How Does the Security access_control Work?](https://symfony.com/doc/current/security/access_control.html).

Securing Controllers and other Code

You can deny access from inside a controller:

  1. // src/Controller/AdminController.php
  2. // ...
  3.  
  4. public function adminDashboard()
  5. {
  6. $this->denyAccessUnlessGranted('ROLE_ADMIN');
  7.  
  8. // or add an optional message - seen by developers
  9. $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'User tried to access a page without having ROLE_ADMIN');
  10. }

That's it! If access is not granted, a specialAccessDeniedExceptionis thrown and no more code in your controller is executed. Then, one of two thingswill happen:

  • If the user isn't logged in yet, they will be asked to log in (e.g. redirectedto the login page).
  • If the user is logged in, but does not have the ROLE_ADMIN role, they'llbe shown the 403 access denied page (which you cancustomize).Thanks to the SensioFrameworkExtraBundle, you can also secure your controllerusing annotations:
  1. // src/Controller/AdminController.php
  2. // ...
  3.  
  4. + use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  5.  
  6. + /**
  7. + * Require ROLE_ADMIN for *every* controller method in this class.
  8. + *
  9. + * @IsGranted("ROLE_ADMIN")
  10. + */
  11. class AdminController extends AbstractController
  12. {
  13. + /**
  14. + * Require ROLE_ADMIN for only this controller method.
  15. + *
  16. + * @IsGranted("ROLE_ADMIN")
  17. + */
  18. public function adminDashboard()
  19. {
  20. // ...
  21. }
  22. }

For more information, see the FrameworkExtraBundle documentation.

Access Control in Templates

If you want to check if the current user has a certain role, you can usethe built-in is_granted() helper function in any Twig template:

  1. {% if is_granted('ROLE_ADMIN') %}
  2. <a href="...">Delete</a>
  3. {% endif %}

Securing other Services

See How to Secure any Service or Method in your Application.

Checking to see if a User is Logged In (IS_AUTHENTICATED_FULLY)

If you only want to check if a user is logged in (you don't care about roles),you have two options. First, if you've given every user ROLE_USER, you canjust check for that role. Otherwise, you can use a special "attribute" in placeof a role:

  1. // ...
  2.  
  3. public function adminDashboard()
  4. {
  5. $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
  6.  
  7. // ...
  8. }

You can use IS_AUTHENTICATED_FULLY anywhere roles are used: likeaccess_control or in Twig.

IS_AUTHENTICATED_FULLY isn't a role, but it kind of acts like one, and everyuser that has logged in will have this. Actually, there are 3 special attributeslike this:

  • ISAUTHENTICATED_REMEMBERED: _All logged in users have this, evenif they are logged in because of a "remember me cookie". Even if you don'tuse the remember me functionality,you can use this to check if the user is logged in.
  • IS_AUTHENTICATED_FULLY: This is similar to IS_AUTHENTICATED_REMEMBERED,but stronger. Users who are logged in only because of a "remember me cookie"will have IS_AUTHENTICATED_REMEMBERED but will not have IS_AUTHENTICATED_FULLY.
  • ISAUTHENTICATED_ANONYMOUSLY: _All users (even anonymous ones) havethis - this is useful when whitelisting URLs to guarantee access - somedetails are in How Does the Security access_control Work?.

Access Control Lists (ACLs): Securing individual Database Objects

Imagine you are designing a blog where users can comment on your posts. Youalso want a user to be able to edit their own comments, but not those ofother users. Also, as the admin user, you want to be able to edit all comments.

Voters allow you to write whatever business logic youneed (e.g. the user can edit this post because they are the creator) to determineaccess. That's why voters are officially recommended by Symfony to create ACL-likesecurity systems.

If you still prefer to use traditional ACLs, refer to the Symfony ACL bundle.

5a) Fetching the User Object

After authentication, the User object of the current user can be accessedvia the getUser() shortcut:

  1. public function index()
  2. {
  3. // usually you'll want to make sure the user is authenticated first
  4. $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
  5.  
  6. // returns your User object, or null if the user is not authenticated
  7. // use inline documentation to tell your editor your exact User class
  8. /** @var \App\Entity\User $user */
  9. $user = $this->getUser();
  10.  
  11. // Call whatever methods you've added to your User class
  12. // For example, if you added a getFirstName() method, you can use that.
  13. return new Response('Well hi there '.$user->getFirstName());
  14. }

5b) Fetching the User from a Service

If you need to get the logged in user from a service, use theSecurity service:

  1. // src/Service/ExampleService.php
  2. // ...
  3.  
  4. use Symfony\Component\Security\Core\Security;
  5.  
  6. class ExampleService
  7. {
  8. private $security;
  9.  
  10. public function __construct(Security $security)
  11. {
  12. // Avoid calling getUser() in the constructor: auth may not
  13. // be complete yet. Instead, store the entire Security object.
  14. $this->security = $security;
  15. }
  16.  
  17. public function someMethod()
  18. {
  19. // returns User object or null if not authenticated
  20. $user = $this->security->getUser();
  21. }
  22. }

Fetch the User in a Template

In a Twig Template the user object is available via the app.user variablethanks to the Twig global app variable:

  1. {% if is_granted('IS_AUTHENTICATED_FULLY') %}
  2. <p>Email: {{ app.user.email }}</p>
  3. {% endif %}

Logging Out

To enable logging out, activate the logout config parameter under your firewall:

  • YAML
  1. # config/packages/security.yaml
  2. security:
  3. # ...
  4.  
  5. firewalls:
  6. main:
  7. # ...
  8. logout:
  9. path: app_logout
  10.  
  11. # where to redirect after logout
  12. # target: app_any_route
  • XML
  1. <!-- config/packages/security.xml -->
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <srv:container xmlns="http://symfony.com/schema/dic/security"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xmlns:srv="http://symfony.com/schema/dic/services"
  6. xsi:schemaLocation="http://symfony.com/schema/dic/services
  7. https://symfony.com/schema/dic/services/services-1.0.xsd">
  8.  
  9. <config>
  10. <!-- ... -->
  11.  
  12. <firewall name="secured_area">
  13. <!-- ... -->
  14. <logout path="app_logout"/>
  15. </firewall>
  16. </config>
  17. </srv:container>
  • PHP
  1. // config/packages/security.php
  2. $container->loadFromExtension('security', [
  3. // ...
  4.  
  5. 'firewalls' => [
  6. 'secured_area' => [
  7. // ...
  8. 'logout' => ['path' => 'app_logout'],
  9. ],
  10. ],
  11. ]);

Next, you'll need to create a route for this URL (but not a controller):

  • Annotations
  1. // src/Controller/SecurityController.php
  2. namespace App\Controller;
  3.  
  4. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  5. use Symfony\Component\Routing\Annotation\Route;
  6.  
  7. class SecurityController extends AbstractController
  8. {
  9. /**
  10. * @Route("/logout", name="app_logout", methods={"GET"})
  11. */
  12. public function logout()
  13. {
  14. // controller can be blank: it will never be executed!
  15. throw new \Exception('Don\'t forget to activate logout in security.yaml');
  16. }
  17. }
  • YAML
  1. # config/routes.yaml
  2. app_logout:
  3. path: /logout
  4. methods: GET
  • XML
  1. <!-- config/routes.xml -->
  2. <?xml version="1.0" encoding="UTF-8" ?>
  3. <routes xmlns="http://symfony.com/schema/routing"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://symfony.com/schema/routing
  6. https://symfony.com/schema/routing/routing-1.0.xsd">
  7.  
  8. <route id="app_logout" path="/logout" methods="GET"/>
  9. </routes>
  • PHP
  1. // config/routes.php
  2. use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
  3.  
  4. return function (RoutingConfigurator $routes) {
  5. $routes->add('logout', '/logout')
  6. ->methods(['GET'])
  7. ;
  8. };

And that's it! By sending a user to the app_logout route (i.e. to /logout)Symfony will un-authenticate the current user and redirect them.

Tip

Need more control of what happens after logout? Add a success_handler keyunder logout and point it to a service id of a class that implementsLogoutSuccessHandlerInterface.

Hierarchical Roles

Instead of giving many roles to each user, you can define role inheritancerules by creating a role hierarchy:

  • YAML
  1. # config/packages/security.yaml
  2. security:
  3. # ...
  4.  
  5. role_hierarchy:
  6. ROLE_ADMIN: ROLE_USER
  7. ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
  • XML
  1. <!-- config/packages/security.xml -->
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <srv:container xmlns="http://symfony.com/schema/dic/security"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xmlns:srv="http://symfony.com/schema/dic/services"
  6. xsi:schemaLocation="http://symfony.com/schema/dic/services
  7. https://symfony.com/schema/dic/services/services-1.0.xsd">
  8.  
  9. <config>
  10. <!-- ... -->
  11.  
  12. <role id="ROLE_ADMIN">ROLE_USER</role>
  13. <role id="ROLE_SUPER_ADMIN">ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH</role>
  14. </config>
  15. </srv:container>
  • PHP
  1. // config/packages/security.php
  2. $container->loadFromExtension('security', [
  3. // ...
  4.  
  5. 'role_hierarchy' => [
  6. 'ROLE_ADMIN' => 'ROLE_USER',
  7. 'ROLE_SUPER_ADMIN' => [
  8. 'ROLE_ADMIN',
  9. 'ROLE_ALLOWED_TO_SWITCH',
  10. ],
  11. ],
  12. ]);

Users with the ROLE_ADMIN role will also have theROLE_USER role. And users with ROLE_SUPER_ADMIN, will automatically haveROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH and ROLE_USER (inherited from ROLE_ADMIN).

For role hierarchy to work, do not try to call $user->getRoles() manually.For example, in a controller extending from the base controller:

  1. // BAD - $user->getRoles() will not know about the role hierarchy
  2. $hasAccess = in_array('ROLE_ADMIN', $user->getRoles());
  3.  
  4. // GOOD - use of the normal security methods
  5. $hasAccess = $this->isGranted('ROLE_ADMIN');
  6. $this->denyAccessUnlessGranted('ROLE_ADMIN');

Note

The rolehierarchy values are static - you can't, for example, store therole hierarchy in a database. If you need that, create a custom[_security voter](https://symfony.com/doc/current/security/voters.html) that looks for the user rolesin the database.

Frequently Asked Questions

  • Can I have Multiple Firewalls?
  • Yes! But it's usually not necessary. Each firewall is like a separate securitysystem. And so, unless you have very different authentication needs, onefirewall usually works well. With Guard authentication,you can create various, diverse ways of allowing authentication (e.g. form login,API key authentication and LDAP) all under the same firewall.
  • Can I Share Authentication Between Firewalls?
  • Yes, but only with some configuration. If you're using multiple firewalls andyou authenticate against one firewall, you will not be authenticated againstany other firewalls automatically. Different firewalls are like different securitysystems. To do this you have to explicitly specify the sameFirewall Context for different firewalls. But usuallyfor most applications, having one main firewall is enough.
  • Security doesn't seem to work on my Error Pages
  • As routing is done before security, 404 error pages are not covered byany firewall. This means you can't check for security or even access theuser object on these pages. See How to Customize Error Pagesfor more details.
  • My Authentication Doesn't Seem to Work: No Errors, but I'm Never Logged In
  • Sometimes authentication may be successful, but after redirecting, you'relogged out immediately due to a problem loading the User from the session.To see if this is an issue, check your log file (var/log/dev.log) forthe log message:
  • Cannot refresh token because user has changed
  • If you see this, there are two possible causes. First, there may be a problemloading your User from the session. See Understanding how Users are Refreshed from the Session. Second,if certain user information was changed in the database since the last pagerefresh, Symfony will purposely log out the user for security reasons.

Learn More

Authentication (Identifying/Logging in the User)

Authorization (Denying Access)