Step 15: Securing the Admin Backend
Securing the Admin Backend
Like for Twig, the security component is already installed via transitive dependencies. Let’s add it explicitly to the project’s file:
$ symfony composer req security
Even if attendees won’t be able to create their own accounts on the website, we are going to create a fully functional authentication system for the admin. We will therefore only have one user, the website admin.
The first step is to define a User
entity. To avoid any confusions, let’s name it Admin
instead.
To integrate the Admin
entity with the Symfony Security authentication system, it needs to follow some specific requirements. For instance, it needs a password
property.
Use the dedicated make:user
command to create the Admin
entity instead of the traditional make:entity
one:
$ symfony console make:user Admin
Answer the interactive questions: we want to use Doctrine to store the admins (yes
), use username
for the unique display name of admins, and each user will have a password (yes
).
The generated class contains methods like getRoles()
, eraseCredentials()
, and a few others that are needed by the Symfony authentication system.
If you want to add more properties to the Admin
user, use make:entity
.
Let’s add a __toString()
method as EasyAdmin likes those:
--- a/src/Entity/Admin.php
+++ b/src/Entity/Admin.php
@@ -75,6 +75,11 @@ class Admin implements UserInterface
return $this;
}
+ public function __toString(): string
+ {
+ return $this->username;
+ }
/**
* @see UserInterface
*/
In addition to generating the entity, the command also updated the security configuration to wire the entity with the authentication system:
We let Symfony select the best possible algorithm for encoding passwords (which will evolve over time).
Time to generate a migration and migrate the database:
$ symfony console make:migration
$ symfony console doctrine:migrations:migrate -n
Generating a Password for the Admin User
Choose whatever you like as a password and run the following command to generate the encoded password:
$ symfony console security:encode-password
Symfony Password Encoder Utility
Symfony Password Encoder Utility
Type in your password to be encoded:
>
Key Value
Encoder used Symfony\Component\Security\Core\Encoder\MigratingPasswordEncoder
Encoded password $argon2id$v=19$m=65536,t=4,p=1$BQG+jovPcunctc30xG5PxQ$TiGbx451NKdo+g9vLtfkMy4KjASKSOcnNxjij4gTX1s
! [NOTE] Self-salting encoder used: the encoder generated its own built-in salt.
[OK] Password encoding succeeded
Insert the admin user via an SQL statement:
Note the escaping of the $
sign in the password column value; escape them all!
Configuring the Security Authentication
Now that we have an admin user, we can secure the admin backend. Symfony supports several authentication strategies. Let’s use a classic and popular form authentication system.
Run the make:auth
command to update the security configuration, generate a login template, and create an authenticator:
$ symfony console make:auth
Select 1
to generate a login form authenticator, name the authenticator class AppAuthenticator
, the controller SecurityController
, and generate a /logout
URL (yes
).
The command updated the security configuration to wire the generated classes:
--- a/config/packages/security.yaml
+++ b/config/packages/security.yaml
@@ -16,6 +16,13 @@ security:
security: false
main:
anonymous: lazy
+ guard:
+ authenticators:
+ - App\Security\AppAuthenticator
+ logout:
+ path: app_logout
+ # where to redirect after logout
+ # target: app_any_route
# activate different ways to authenticate
--- a/src/Security/AppAuthenticator.php
+++ b/src/Security/AppAuthenticator.php
@@ -96,8 +96,7 @@ class AppAuthenticator extends AbstractFormLoginAuthenticator implements Passwor
return new RedirectResponse($targetPath);
}
- // For example : return new RedirectResponse($this->urlGenerator->generate('some_route'));
- throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
+ return new RedirectResponse($this->urlGenerator->generate('admin'));
}
protected function getLoginUrl()
Tip
How do I remember that the EasyAdmin route is admin
(as configured in App\Controller\Admin\DashboardController
)? I don’t. You can have a look at the file, but you can also ran the following command that shows the association between route names and paths:
A security system is made of two parts: authentication and authorization. When creating the admin user, we gave them the ROLE_ADMIN
role. Let’s restrict the /admin
section to users having this role by adding a rule to access_control
:
--- a/config/packages/security.yaml
+++ b/config/packages/security.yaml
@@ -35,5 +35,5 @@ security:
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- # - { path: ^/admin, roles: ROLE_ADMIN }
+ - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
The access_control
rules restrict access by regular expressions. When trying to access a URL that starts with /admin
, the security system will check for the ROLE_ADMIN
role on the logged-in user.
Authenticating via the Login Form
If you try to access the admin backend, you should now be redirected to the login page and prompted to enter a login and a password:
Log in using admin
and whatever plain-text password you encoded earlier. If you copied my SQL command exactly, the password is .
Note that EasyAdmin automatically recognizes the Symfony authentication system:
Try to click on the “Sign out” link. You have it! A fully-secured backend admin.
Note
If you want to create a fully-featured form authentication system, have a look at the make:registration-form
command.
This work, including the code samples, is licensed under a license.