Yo guys! You finally made it to the security course: you brave, brave souls. Whatever, these days, security isn't scary - it's super fun! You've got traditional login forms, Facebook authentication, GitHub authentication, and API authentication with JSON web tokens, just to name a few. When you're doing something with security these days, it's usually pretty darn fun. And we're going to learn enough so that you can implement whatever crazy, insane security system you want.

But, the only way to secure your new security skills it to feel secure in my recommendation that you code along with me. You guys know the drill: download the course code unzip it and look for the start/ directory. That'll have the same code that I have here. Open up the README file to find all the setup details. At the end, you'll open up a new tab and run:

./bin/console server:run

to start the built-in web server.

Authentication vs Authorization (Fight!)

Aquanauts assemble... to talk about security!

Security has two big parts. The first is authentication - this is all about who you are - and we'll cover it first. Authentication is the tough stuff, and there's a lot of variation - login forms, social media auth, API stuff - you get it.

The second big piece is authorization, and this doesn't care about who you are, just whether or not you have fins. I mean, whether or not you have permission to take an action. Authorization comes later.

What about FOSUserBundle?

Before swim there, let's talk about a super-famous bundle: FOSUserBundle. You might be wondering, should I use this? What does it do? Or, did I turn the oven off?

First, we will not use this bundle, but it is great and you did turn the oven off... probably.

It gives you a lot of free features that we will build by hand. But FOSUserBundle does not give you any special "security" system - it's much less interesting than that, in a good way! The bundle gives you just two things:

  1. A User entity in case you need to store users in the database
  2. A bunch of routes and controllers

for things like your login form, registration and reset password. Those are all things you can easily build yourself... but if you need them, why not use the bundle?

Anyways, we won't use it, and that'll be the best path to learn how the security system works. But when you finish, you might save yourself some time using FOSUserBundle.

Create that User Class

Now, back to authentication. Here's our first goal: create a login form where the user can sign in with their email and password. In this app, we'll load user info from the database.

No matter how your users will authenticate, the first step is always the same: create a User class.

In your Entity directory - create a new class called User. The only rule is that this must implement a UserInterface. Add that:

... lines 1 - 2
namespace AppBundle\Entity;
... lines 4 - 5
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
... lines 10 - 28

I'll use Command+N - or the "Code"->"Generate" menu - and select "Implement Methods". Select all the new methods:

... lines 1 - 2
namespace AppBundle\Entity;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
public function getUsername()
public function getRoles()
public function getPassword()
public function getSalt()
public function eraseCredentials()

Oh, and let's move getUsername() to the top: it makes more sense up there.

Is User an Entity?

Notice I did put my User class inside of the Entity directory because eventually we will store users in the database. But, that's not required: sometimes user details are stored somewhere else - like a central authentication server. In those cases, you will still have a User class, you just won't store it with Doctrine.

More on that as we go along.

Ok, we've got the empty user class: let's fill it in!

Leave a comment!

  • 2018-07-25 Diego Aguiar

    Hey Ricard Espinàs Llovet

    Nice question! I had to do some research ;)

    Look's like that's a feature that haven't been finished yet
    but there is a workaround - manually refreshing the user-token via subscriber. For more details about how the code looks like check this thread


  • 2018-07-25 Ricard Espinàs Llovet

    Hello again, and thank you very much for your tutorials.
    I followed this authentication system and I got an error I can't solve. If I update my roles or the roles from another user and I don't logout and log in again the app get crazy remembering somehow the old roles. I leave the link from stackoverflow here.

    Thank you very much for advance.

  • 2017-10-11 Diego Aguiar

    Hey Kasia Tychańska

    I believe you forgot to run
    $ composer install

    Try that, and tell me what happened. Also, there is a README.txt file with more installation instructions


  • 2017-10-11 Kasia Tychańska

    could you please help me? When I try to open downloaded files I get this error.
    What should I do?

    Warning: require_once(C:\xampp\www\school\vendor/composer/autoload_real.php): f
    iled to open stream: No such file or directory in C:\xampp\www\school\vendor\au
    oload.php on line 5
    PHP Fatal error: require_once(): Failed opening required 'C:\xampp\www\school\
    endor/composer/autoload_real.php' (include_path='C:\xampp\php\PEAR') in C:\xamp
    \www\school\vendor\autoload.php on line 5

    Fatal error: require_once(): Failed opening required 'C:\xampp\www\school\vendo
    /composer/autoload_real.php' (include_path='C:\xampp\php\PEAR') in C:\xampp\www
    school\vendor\autoload.php on line 5

  • 2017-08-15 weaverryan

    Yo Mike!

    The Role use statement is totally unnecessary - don't worry about it :). I believe it is added because the PHPDoc above the getRoles() method mentions it. I'm not sure why it would not generate now... but it's definitely not needed. Good eye ;)


  • 2017-08-14 Mike

    PHPStorm doesn't autogenerate the use statement for "Symfony\Component\Security\Core\Role\Role" (SF 3.3.6). In the video it seems that oh-storm is generating it while we implement all methods. Do you know why? Is this necessary?

  • 2017-07-31 Nina

    Could I give access to this file execution permissions on Windows?

  • 2017-07-31 Victor Bocharsky

    Hey Nina,

    Actually, it's the same... but there's a subtle difference. The more expanded example is:

    "php ./bin/console server:run"

    That's because Symfony console (which is ./bin/console) is written in PHP, i.e. you can open ./bin/console file with PhpStorm or other editor and you'll find a PHP code there. So to run PHP code we need a PHP interpreter, i.e. call php at first and then pass it a file as an argument: "php ./bin/console". But Linux based OS like Ubuntu, Mac OS, etc. allow you to skip it and execute this file directly, but to get it working you need this file has execution permissions. It means that on some OS your can skip PHP prefix and execute this command directly like just "./bin/console", but if it doesn't work and you have an error that the file can't be executed - you can always run this file through PHP interpreter like: "php ./bin/console". If you're on Windows, most probably you need to use this expanded example. Otherwise, try the short one first. If it works - great, use it! If not, just fallback to the expanded syntax. Ryan records screencasts on a Mac, that's why on the video you can often see the short example, but we try to use expanded example in our course scripts.


  • 2017-07-30 Nina

    Please, explain me.
    When I use cmd I write for example
    php bin/console server:run
    In your course write
    ./bin/console server:run

    Why such difference?
    Why your don't need write php forward bin/console server:run

    May be, I need to read something to understand this?

  • 2017-05-17 Diego Aguiar

    haha that's funny ;)

  • 2017-05-17 Mike Ritter

    cookies? ice cream? i'm hungry.

  • 2017-05-02 Diego Aguiar

    Hey Brian!

    I think you forgot to run
    $ composer install
    If that's not the case, something might went wrong when replacing old files, try deleting the current project and unzipping again the downloaded project


  • 2017-04-29 Brian


    So I downloaded the course, and replaced my old code with this start code. Now I cannot get into the server... Think you can help?

    Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "KnpMarkdownBundle" from namespace "Knp\Bundle\MarkdownBundle".
    Did you forget a "use" statement for another namespace? in /Users/Brian/aqua_note/app/AppKernel.php:19

    Stack trace:
    #0 /Users/Brian/aqua_note/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(406): AppKernel->registerBundles()
    #1 /Users/Brian/aqua_note/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(113): Symfony\Component\HttpKernel\Kernel->initializeBundles()
    #2 /Users/Brian/aqua_note/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(68): Symfony\Component\HttpKernel\Kernel->boot()
    #3 /Users/Brian/aqua_note/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(121): Symfony\Bundle\FrameworkBundle\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

    #4 /Users/Brian/Glamp in /Users/Brian/aqua_note/app/AppKernel.php on line 19

    Thank you :)

  • 2017-04-19 Jelle Schouwstra

    Thanks, Ryan, I'll be using server:run from now on ;)

  • 2017-04-17 weaverryan

    Yo Jelle Schouwstra!

    Great question! There are two ways to start the built-in server: server:start and server:run. The *only* difference between the two is that server:run "blocks" your terminal afterwards - i.e. you can't type anything in that terminal anymore until you type "ctrl+c", which kills the server. However, when you use server:start, it starts a background process and returns your terminal to you. Later, you can run server:stop to kill that background process. But, this little dance requires the pcntl extension :). I think when you're typing "y", it's just falling back to using server:run

    We show server:run only in our tutorials because (A) it works for everyone and (B) sometimes you can forget you have a server started, then try to start one later and get an error. In other words, the behavior of server:run causes less surprises :).


  • 2017-04-16 Jelle Schouwstra

    When I start the built-in server I get the error:

    [ERROR] This command needs the pcntl extension to run.

    You can either install it or use the "server:run" command instead to run the built-in web server.

    I can still start the server with "y" but I'm curious why the error appears?

  • 2016-10-26 weaverryan

    Yo Terry! We do this right inside Screenflow, our screen-recording/video-editing software. The magic is mostly worked by Leanna - she's gotten pretty good at this stuff over the years :)

  • 2016-10-26 Terry Caliendo

    Just curious what software you use to make such great animations lika at the beginning of this video?