composer require security

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Welcome back friends! I'm so happy that you've stumbled into my Symfony 5 security tutorial for a bunch of reasons. The first is that well... uh... the site that we've been building has NO security... and the raptors are starting to jiggle the door handles.

The other reason is that, once we make it to the maintenance shed on other side of the compound, we're going to explore Symfony's new security system, called the "authenticator" system. Ooh. If you've used the old system, you'll feel right at home. If you're new to Symfony security, you chose a great time to start. The new system is easier to learn and understand... but it's also more powerful.

Project Setup

And because the security system isn't going to come online by itself, let's get to work. To learn how to authenticate & authorize & do other cool security stuff at a pro level, you should definitely download the course code from this page and code along with me. Making real-world mistakes.... yeah, it's the best way to remember this stuff.

After unzipping the file, you'll find a start/ directory with the same code that you see here. Pop open the README.md file for all the setup instructions. The last step will be to find a terminal, move into the project and start a web server. I'm going to use the symfony binary for this:

symfony serve -d

This starts up a new server at https://127.0.0.1:8000. Open that in your browser... or be lazy and run:

symfony open:local

to... "delegate" the work to someone else. Say hello to Cauldron Overflow! A question and answer site for witches and wizards, who... unfortunately... keep casting their spells live on production first without testing them... and usually on a Friday afternoon. Sheesh. Then they come here to ask how to undo the damage.

Installing Security

Because Symfony's philosophy is to start small and then allow you to install the stuff you need later, right now our app... literally does not have a security system.

That's no fun, so let's install one! Go back to your terminal and run:

composer require security

This installs Symfony's security bundle. After it finishes... run:

git status

to see what its recipe did. In addition to the normal stuff, it added one new configuration file: security.yaml. Let's go check that out: config/packages/security.yaml:

security:
# https://symfony.com/doc/current/security/authenticator_manager.html
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#c-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
users_in_memory: { memory: null }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: users_in_memory
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
# 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: ^/profile, roles: ROLE_USER }

As you hopefully guessed by its name, this file powers the security system! By the time we're done, each section in here will be simple and boring to you. I love when programming stuff is boring.

enable_authenticator_manager

Oh, but see this enable_authenticator_manager key?

security:
# https://symfony.com/doc/current/security/authenticator_manager.html
enable_authenticator_manager: true
... lines 4 - 29

In Symfony 5.3 - the version I'm using - the old and new security systems live side-by-side and you get to choose which one you want! When you set enable_authenticator_manager to true, you are activating the new system. Yay! Shiny! If you're working on a legacy project and need to learn the old system, check out our Symfony 4 Security tutorial. It's pretty cool too!

Authentication & Authorization

Anyways, when you talk about security, there are two big parts: authentication and authorization. Authentication asks the question, "who are you"? And "can you prove it?" Users, login forms, remember me cookies, passwords, API keys... all of that stuff is related to authentication.

Authorization asks a different question: "Should you have access to this resource?" Authorization doesn't care much about who you are... it's all about allowing or denying access to different things, like different URLs or controllers.

In Symfony, or really in any security system, authentication is the tricky part. I mean, just think about how many ways there are to authenticate! Login forms, API token authentication, social authentication with OAuth, SSO's, LDAP, putting on a fake mustache and walking confidently passed a security guard. I mean... the possibilities are endless. But I also think that authentication is super fun.

So next: let's start on our journey into the new shiny authenticator system by creating the most basic part of authentication: a user class.

Leave a comment!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.4.1 || ^8.0.0",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "babdev/pagerfanta-bundle": "^3.3", // v3.3.0
        "composer/package-versions-deprecated": "^1.11", // 1.11.99.4
        "doctrine/annotations": "^1.0", // 1.13.2
        "doctrine/doctrine-bundle": "^2.1", // 2.4.3
        "doctrine/doctrine-migrations-bundle": "^3.0", // 3.1.1
        "doctrine/orm": "^2.7", // 2.10.1
        "knplabs/knp-markdown-bundle": "^1.8", // 1.9.0
        "knplabs/knp-time-bundle": "^1.11", // v1.16.1
        "pagerfanta/doctrine-orm-adapter": "^3.3", // v3.3.0
        "pagerfanta/twig": "^3.3", // v3.3.0
        "phpdocumentor/reflection-docblock": "^5.2", // 5.2.2
        "scheb/2fa-bundle": "^5.12", // v5.12.1
        "scheb/2fa-qr-code": "^5.12", // v5.12.1
        "scheb/2fa-totp": "^5.12", // v5.12.1
        "sensio/framework-extra-bundle": "^6.0", // v6.2.0
        "stof/doctrine-extensions-bundle": "^1.4", // v1.6.0
        "symfony/asset": "5.3.*", // v5.3.4
        "symfony/console": "5.3.*", // v5.3.7
        "symfony/dotenv": "5.3.*", // v5.3.8
        "symfony/flex": "^1.3.1", // v1.17.5
        "symfony/form": "5.3.*", // v5.3.8
        "symfony/framework-bundle": "5.3.*", // v5.3.8
        "symfony/monolog-bundle": "^3.0", // v3.7.0
        "symfony/property-access": "5.3.*", // v5.3.8
        "symfony/property-info": "5.3.*", // v5.3.8
        "symfony/rate-limiter": "5.3.*", // v5.3.4
        "symfony/runtime": "5.3.*", // v5.3.4
        "symfony/security-bundle": "5.3.*", // v5.3.8
        "symfony/serializer": "5.3.*", // v5.3.8
        "symfony/stopwatch": "5.3.*", // v5.3.4
        "symfony/twig-bundle": "5.3.*", // v5.3.4
        "symfony/ux-chartjs": "^1.3", // v1.3.0
        "symfony/validator": "5.3.*", // v5.3.8
        "symfony/webpack-encore-bundle": "^1.7", // v1.12.0
        "symfony/yaml": "5.3.*", // v5.3.6
        "symfonycasts/verify-email-bundle": "^1.5", // v1.5.0
        "twig/extra-bundle": "^2.12|^3.0", // v3.3.3
        "twig/string-extra": "^3.3", // v3.3.3
        "twig/twig": "^2.12|^3.0" // v3.3.3
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.3", // 3.4.0
        "symfony/debug-bundle": "5.3.*", // v5.3.4
        "symfony/maker-bundle": "^1.15", // v1.34.0
        "symfony/var-dumper": "5.3.*", // v5.3.8
        "symfony/web-profiler-bundle": "5.3.*", // v5.3.8
        "zenstruck/foundry": "^1.1" // v1.13.3
    }
}