Symfony 3 Security: Beautiful Authentication, Powerful Authorization


What you'll be learning

Ah, security! Quick run!

Wait, come back! Security in Symfony is awesome! Seriously, between things called "voters" and the Guard authentication system, you can do anything you want inside of Symfony, and the code to do it is simple and expressive.

Security has two sides: authentication (who are you?) and authorization (do you have access to do X). We'll talk about each of these, creating an traditional form login system and and API token authentication system using Json web tokens (not as scary as they sound!). Then, we'll turn to authorization, with roles, voters and other good stuff:

  • Security & Firewall Fundamentals
  • Creating a custom login form
  • Making a User (ooOOOoo)
  • User Providers (why you need them, but don't care)
  • Password Encryption
  • Logging out!
  • Protecting entire URLs with access_control(s)
  • Checking access with roles! ROLE_USER
  • Denying access in a controller
  • What are voters?
  • Role hierarchies
  • Impersonation (switch_user)
  • Registration Form
  • Manual authentication

... and how to create a back door into your site. Just kidding! Let's make some secure sites!

Your Guides

Ryan Weaver Leanna Pelham

Buy Access

Questions? Conversation?

  • 2018-07-27 Diego Aguiar

    Hey Paweł Chry

    In that case you could use AWS S3 service for data storage, or, if you are storing files locally, then, you may want to store them out of the web directory and then create a controller's action that will *do* that "serving" logic (There is where you can check roles)


  • 2018-07-27 Paweł Chry

    Hi, Where should I store files uploaded by users to prevent them to be available by everyone? I mean, if I store files in web/ directory then everyone have access to them by writing proper url

  • 2018-06-28 Mamadou soumahoro

    Thank for your quick response Victor. You guys from KNPUniversity are really nice. I think I will wait for the new tutorial.

  • 2018-06-25 Victor Bocharsky

    Hey Mamadou,

    Thanks for your kind words! You can wait for this new course based on Symfony 4 and our brand Stellar project, we're really want to release it soon, but I have no estimations yet. So, if you impatient, you can start with this one - the code is almost the same, well, except that you need to do it in a Symfony 4 way with Symfony Flex, you know, installation process and file structure are a bit different in Symfony 4. If you find any issues with Symfony 4 - let us know in comments section and we'll help you.


  • 2018-06-24 Mamadou soumahoro

    Hey, Ryan. Thanks for this great tutorials. I just wanted to know if it is compatible with symfony 4 or should I wait for a specific tutorial. Thanks bro and good job.

  • 2018-05-14 Diego Aguiar

    Hey Sasa Milivojevic

    I'm not sure if this is the best way todo it but at least it will give you the flexibility that you require.
    If you make use of the "always redirect to the default page" system, then you can implement a custom route action that will work as a central entry point, where you can implement all the logic required to decide the proper redirection


  • 2018-05-14 Sasa Milivojevic

    Hi Ryan, I watch videos and everything working fine, but I have problem I want to redirect user by roles after login. Is there some easy solution?

  • 2018-01-15 Victor Bocharsky

    Hey Gunnar,

    Good question! You can take a look at FOSUserBundle which already has this functionality implemented out of the box, you just need to enable it. If you do not want to install an entire bundle and you've already implemented login/register features by yourself, well, you can grab some already written logic from FOSUserBundle to implement password resetting by yourself. But the concept is simple: when user request a password reset for his email - you need to generate a unique ID generally called "token", e.g. an md5 hash for that user. It's a good idea to add some kind of TTL for this token to make it token not active after a while for security reasons. This token should be sent to user's email as a link, and when user click this link - if token is valid and not expired - you show a password reset form, i.e. a new password field, or 2 fields: "new password" and "confirm new password". When user enter a new password - encrypt and store it in DB, also clearing the password resetting token for security reasons.


  • 2018-01-14 Gunnar Polte

    Hey Ryan,
    it was a pleasure to follow your tutorial.

    I would like to know one more things.
    - How to create a password forgotten functionality?

    Could you please give some advice.
    Thank you.

  • 2017-03-23 Blueblazer172

    Thanks for that snippet;) really awasome;)

  • 2017-03-22 weaverryan

    Hey Blueblazer172!

    Good question! Of course, the answer is always yes - just a matter of how :). And by the way, it may or may not be worth doing - unless we've made a mistake (e.g. linking to a page the user doesn't have access to) or a bad user is scanning for vulnerabilities, this situation should never happen.

    But, here's the correct way to do it: In that doc, you create a class with a function that is called in this exact situation. Your setup will probably look something like this:


  • 2017-03-22 Blueblazer172

    is there a way to add a flash message for a AccessDeniedException?
    so basicly when a user does not have access to that page he should be redirected to the homepage with addFlash.
    Have a look at this:

    class AccessDeniedExceptionController extends Controller
    public function AccessDeniedExceptionAction()
    $this->addFlash('error', 'Error 403! You dont have access to that page');
    return $this->redirectToRoute('homepage');
  • 2017-03-08 Lasha Kitia

    Thank you for giving me the answer super fast, Ryan.
    I love Knp <3

  • 2017-03-08 weaverryan


    Unfortunately, I think this is normal / expected. I don't believe that PhpStorm has any intelligence to know what the exact User class is for your User. In other words, when you say app.user, PhpStorm has no idea what object this returns, and so gives no auto-completion. This *would* be a great feature for the plugin however! It's rare that I find something that the plugin doesn't do :).


  • 2017-03-08 L

    Hello Ryan.

    I am getting no autocomplete in security.yml when I'm specifying provider entity class and also in twig after "app.user." Php storm cannot see that I already have getUsername() function.
    Can you tell me please what did I do wrong?
    Thank you in advance.

  • 2017-01-27 Victor Bocharsky

    You're welcome! I love easy fixes ;)


  • 2017-01-27 Jhonatan Casaliglla

    Thanks a lot...! The problem was in the database because password field length is not long enough... Thanks again

  • 2017-01-26 Victor Bocharsky

    Hey Jhonatan,

    There're a few possible problems:
    - Please, check in the DB that password for the user in password field is not a plain user password (i.e. password encoded) and check if its field length is long enough, I mean that password hash wasn't cutted;
    - You pass invalid arguments into the isPasswordValid($user, $password) - please, do dump($user, $password); variables and ensure that you pass the correct user object (with which you intend to log in) and that $password is exactly what you typed in login form password field;

    Let me know if it helps.


  • 2017-01-26 Jhonatan Casaliglla

    Hey Ryan... please I need help. I got an error because it the method isPasswordValid() always returns false and I can't log in.

  • 2017-01-13 Victor Bocharsky

    Ah, I bet it's default font in PhpStorm for Ubuntu. It's a bit weird to have different default fonts for different OS but anyway it's easy fix. ;)


  • 2017-01-12 weaverryan

    Hey Javier!

    Are you looking for this? Or something else?

    Let me know, and cheers!

  • 2017-01-12 Cristian Merli

    My default is called "Source Code Pro" but it's not as nice. And I am using Ubuntu

  • 2017-01-12 Javier Mendez

    do you have a class that takes this Authentication to JWT? if we already implemented this type of authentication and then decide to stop using sessions and we want to use tokens...

  • 2017-01-12 Victor Bocharsky

    Hey Cristian,

    I have Menlo too, and it was the default PhpStorm's font for me. But I think font could be different for different OS.


  • 2017-01-12 weaverryan

    Yo Christian!

    It's called Menlo - I honestly can't remember if I changed the default Darcula to this one, but it sounds like I did. So, go get Menlo! I also use it for code in presentations.


  • 2017-01-11 Cristian Merli

    Hi what font are you using?? I have the default that comes with Darcula but it doesn't look the same. I love the font I see in these videos!

  • 2016-10-18 weaverryan

    Yo Mike!

    It's not in this tutorial, but it is right here: and also here: The first is more up-to-date (after we made a simplification to voters) but the second has a little bit more background detail. Voters are awesome... so enjoy!


  • 2016-10-18 Mike Milano

    Voters are mentioned in the description but are they covered here? If so, which video are they covered in?

    It's been a while since I've done this course and I'd like to skip to content relevant to voters.

  • 2016-09-19 weaverryan

    That's probably not a bad idea - I try to avoid Doctrine listeners if I can, and instead do work in services, and call those services when needed. Doctrine is great, but Doctrine listeners are a weird place, where you're already right in the middle of saving something. Not a bad policy to avoid :).


  • 2016-09-18 Lee Ravenberg

    Thanks Ryan! I really appreciate you taking the time to look at it.

    I finally decided to remove the doctrine Password Hash Listener and encode the passwords at an other place. This works fine. I am still curious about what the cause of the issue is though. Doctrine scares me.

  • 2016-09-12 weaverryan

    Yo Lee!

    Haha, sorry to disappoint ;). Once you've got authenticators down, you're a pro. Well, there's *always* more to security :).

    I just left a comment on your SO - it's definitely something minor: based on your post, I think you understand things really well. I actually *always* call persist() - even though I don't need to - so I'm less familiar with what might ultimately be causing it.


  • 2016-09-12 Lee Ravenberg

    Followed the entire course and learned a lot! Authentication is awesome. When I finished the last video I really went like 'doh.. are we done already?'. So I went on to build a Password Reset form by making a LoginHash entity. But I ran into a problem when storing the new password into the database. If anyone is curious, I made a Stackoverflow post here:

  • 2016-09-02 weaverryan

    Ah, good find! I've totally done that sort of thing before :D


  • 2016-09-02 Shane MAIAU

    I'm so dumb, it's was a mistake in my code.

    In my User entity i wrote this code :
    public function getPassword()
    return $this->getPassword();

    that's why i have an infinite loop.

    Thanks again for your time and your support you rocks !

  • 2016-09-02 weaverryan

    Yo Shane!

    Ah, well good debugging at least with the "intercept redirect"! That helps narrow things down. What's the 500 error message that you get after the redirect? It definitely makes me think that something is misconfigured with your "user provider" -

    And thanks for the nice words - it makes it a lot more fun for us when this stuff is really useful to people!


  • 2016-09-02 Shane MAIAU

    Hi Ryan,

    I have a weird error and I still figuring out why I have this issue.
    I created my Authenticator and I can login.

    When I intercept the redirect, I can see that my login form is working but when I redirect to the homepage I have an error 500.

    I don't know why maybe I have an infinite loop after the login ?

    Thanks again for your help and your amazing tutorials.


  • 2016-08-16 Vlad

    Thank you, Ryan, that's great! I'll shoot you an email, once I finish the course!

  • 2016-08-15 weaverryan

    Hey Vlad!

    This is something we're actually working on right now (and your feedback about what you need on the certificate is very useful!). But, we'd be happy to make a certificate for you before then so you have it. Just send us an email ( with the details (e.g. your full name).

    Happy this topic hit on your continuing ed requirements - that's awesome :).


  • 2016-08-15 Vlad

    Hi Ryan,
    Is there any way to get a completion certificate?
    This course is perfect for renewal of one of my certifications as part of continuing education, but I need to provide a completion certificate with the course name and my full name on it.
    Thank you!

  • 2016-07-20 weaverryan

    These are awesome resources - thanks for sharing them :). And yes, we would definitely do this on Symfony 3!

  • 2016-07-19 Chen Dong

    Hi Ryan, thanks for the reply. I think I have got some real world examples for you and this might be (may not be) seem like a challenge... But we'll be so happy if you accept this challenge; BTW, will it be possible to experimenting them on Symfony3 framework as well? Many thanks and the best regards! :-)

    Push it to the limits - Symfony2 for High Performance needs:

    Handling 1 Billion requests a week with Symfony2:

    The Easy Way Of Building A Growing Startup Architecture Using HAProxy, PHP, Redis And MySQL To Handle 1 Billion Requests A Week:

  • 2016-07-19 weaverryan

    Hey Chen!

    Ah, thank you! I think this a great topic - more and more people are asking for something like this. Which parts are most important to you? Tuning the bottom-line speed of each request? Caching? Something else?

    I'm adding it to our list right now :).


  • 2016-07-19 Victor Bocharsky

    Hey Chen,

    We don't plan any "Symfony Optimization" courses in the near future. Usually, a performance optimization inversely to the maintenance, I mean, that if you optimized performance of your application very cool, probably, you will find it difficult to maintenance code of this application and make some changes in the future. I would advise you to look in the direction of cache like Symfony HTTP cache which provides out of the box, or more complex solutions like Memcache or Redis.

    You also could probably check the, which is a cool profiler tool. It allows you to find a bottleneck in your application and helps to find a proper solution how to improve performance of your application.


  • 2016-07-19 Victor Bocharsky


    You can simply check if user has a role in templates with "is_granted()" Twig function along with "include" Twig tag and then render different templates based on result of condition. For example:

    {% if is_granted('ROLE_MANAGER') %}
    {% include '_manager.html.twig' %}
    {% else %}
    {% include '_default.html.twig' %}
    {% endif %}

    Or even add the same conditions in your action and render different templates based on user role.

    Sometimes it's useful to have different actions/routes in controller for different roles, but anyways, you will have to add conditions to build links to these different routes.

    If your users have a lot of roles, probably you need to think about custom Voters or even Symfony ACL.


  • 2016-07-19 Chen Dong

    Hi Ryan and Leanna, I just wanted to say thank you for all the amazing tuts, I'm just wondering will there be any tuts regarding to Symfonys' Performance Tuning in the future?

  • 2016-07-16 JLChafardet

    Hey guys! sorry to ask something that maybe has already been asked but.

    based on the roles here, can I render specific views?

    lets not go to super granulated permissions, that seems to be a really tiresome-bothersome-painintheassish task, but roles based, could that be managed in a "if user belongs to X role" render this view, else render this other?

    I'm aware i can hide specific areas in views based on that, tho, what about views that would significantly change? having that bunch of conditions wouldnt be a pain?

  • 2016-07-15 Chen Dong

    Your Courses about Symfony are amazing, I'm wondering will there be any tuts related to Symfony Optimization coming in the Future? Cause I personally think that the optimized environment or configuration or code might be faster than the default.

  • 2016-07-15 Victor Bocharsky

    I think I know why: "isXmlHttpRequest()" works if your JavaScript library sets an X-Requested-With HTTP header. It is known to work with common JavaScript frameworks. But if this header wasn't passed - it won't work, so you need to add another custom check for it.


  • 2016-07-14 fredrsf

    Hi Victor Bocharsky , yes i tried to do it as this tutorial. I used 'fetch' from es6 and my user stayed anonimus (I don't understood why). When i change it to XMLHttpRequest, registration works correct. Thank you!!!

  • 2016-07-14 Victor Bocharsky

    Hey fredrsf ,

    Did you see the latest chapter in this course: Automatically Login after Registration. It explain how to do it, except that you should wrap `$this->get('security.authentication.guard_handler')->authenticateUserAndHandleSuccess(...)` call with additional condition:

    if ($request->isXmlHttpRequest()) {
    return $this->get('security.authentication.guard_handler')

    If you'll send an AJAX request - `isXmlHttpRequest()` returns true in this case. And don't forget to handle that case when you have a normal (not AJAX) request.


  • 2016-07-14 fredrsf

    Hello everyone, how can i do automatically login after registration, if registration form data came from ajax request?

  • 2016-06-29 JLChafardet

    lets hope the rest comes soon enough!

  • 2016-06-28 JLChafardet

    oh at last! cant wait to get started.

  • 2016-06-22 weaverryan

    Good news Bjorn - next week! We're doing final edits on it right now :)


  • 2016-06-22 Bjorn Larson

    Please I need this tutorial. when is it coming out ???

  • 2016-06-20 Victor Bocharsky

    We'll have a script content without code blocks first. Code blocks will be added a bit later, after screencasts.

  • 2016-06-18 JLChafardet

    Thats amazing! indeed would be awesome to be able to start even without the screencast, with the scripts maybe?

  • 2016-06-18 weaverryan

    This will be released the week after next (so about 9 days) - but parts of it may be released next week :)

  • 2016-06-17 Victor Bocharsky

    Ah, OK!

    If you have not found any solution yet, could you explain me again what exactly don't work as you want in this code? I'll try to help you with it too.


  • 2016-06-16 Julian

    This works the same way as the Controller before. There is still a default render to /login but I will check out now how to customize the Routes after a logout. Thank you so much and I'm also thankfull for any further advices!

  • 2016-06-16 Victor Bocharsky

    Hey, do you consider isGranted('IS_AUTHENTICATED_REMEMBERED')? It returns true for all logged in users, even if they are logged in because of a "remember me cookie". (Notice that I don't use negation (! sign) in if statement):

    public function loginAction()
    if ($this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
    return $this->render('MainBundle:Default:show.html.twig');

    return $this->render('MainBundle:Default:log_index.html.twig');

    Please, let me know if it helps you!

  • 2016-06-16 Julian

    Thanks a lot dude! It was definitly my own YML mistake. I just have still a routingproblem. When my auth_token is set Annonymous my project is still rendering the default login form. When I have authorization he renders the show.html I just want to have rendered there ;). My dream is to render the log_index.html if a user logsout or is at the Annonymous-Status.

  • 2016-06-16 Victor Bocharsky

    BTW, you could check full security reference here, or just use Symfony console command:

    bin/console config:dump-reference security
  • 2016-06-16 Victor Bocharsky

    Hey, Julian!

    What about the second problem, it's difficult to understand from your message without proper formatting, but I was tricky and was able to see what's the problem :) You placed `anonymous` key under `logout` but should under your firewall name like:

    path: /logout
    target: /log_index
    anonymous: true

    Please, fix it first and let me know if your first issue still exist.


  • 2016-06-16 Julian

    Hi Guys! I'm using the FOSUserBundle and I have two Problems while logging out.
    I have set up a MainController and I want to have a different view for ppl who are logged in. So I let my MainController do this:

    * @Route("/")
    public function loginAction()
    if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY'))
    return $this->render('MainBundle:Default:log_index.html.twig');
    return $this->render('MainBundle:Default:show.html.twig');


    It kinda works BUT when I log out there is the default login page rendered and not my own log_index.html what I want to render when a user logs out.

    2. Problem is using the firewall correctly
    When I want my firewall to handle logouts like that:

    path: /logout
    target: /log_index
    anonymous: true

    Symfony throws Excetions like I'm using the wrong option there..

    Maybe you can help me.


  • 2016-06-15 JLChafardet

    Oh well anxiously waiting for this tutorial series to be released! I learnt a lot from Starting in Symfony 3 series, cant wait to get to this new part!

  • 2016-06-04 Jan R.

    Hey, Ryan. Thanks for great tutorials. Helped very much to master Symfony! Watched them on one breath! Can't wait for Security tutorial to be released. Keep going on!

  • 2016-05-19 weaverryan

    Thank you so much for this! And you also highlighted some problems with the official docs that we can fix :).

    I have added this to our internal screencast idea list. There's no public place to vote for ideas currently. Well, no "official" place - often times people click the "Ideas or Feedback" button on the bottom right of the page and add the idea there. Other people vote on those. We've been thinking about adding a proper spot on the site - it would be great to crowdsource what people are having most trouble with!


  • 2016-05-19 Yoni L.

    Ok, to begin, most of the tutorials available describe how to use translator from scratch [], but the translator service is already active and the name is "translator.default" for injection.

    - The fact that symfony can manage and create the file they are always talking about in that tutorials (xml, po, array...) with the console.

    I know that we can use anything to render view but we can suppose that we use the excellent twig part.
    I use {%trans%} in twig, how to generate easily the translation file in fr_FR and en_GB for example and where is it created?
    I was force to google that (or Bing or yahoo...) to finaly understand: It's so easy...
    - the translation folders which is a very sensitive point of 3 lines in the doc

    If i was looking for a tutorial, I would like to have:
    - quick overview of the global process
    - (how to) the front end translation (twig),
    - (how to) the back end translation (for api, ajax, error thrown...).
    - the awesome translation file generation and the console debuging.
    - ice on the cake for fun: custom translator with twig filter.

    Often when already have some text to translate, and the official doc is beginning at the opposite of that.
    Do we have a sugestion page on the KnPU site with vote?

  • 2016-05-19 weaverryan

    Hi Yoni!

    We don't have an active plan to talk about translations, but it's a good topic! I would love to know what specific pieces were most difficult for you - we could use that to plan the tutorial!


  • 2016-05-18 Yoni L.

    Hi Ryan and Leanna,
    Did you plan a tutorial for translation service? I spent so much time to find usefull and up-to-date infos on the official doc, it could be usefull.


  • 2016-05-18 weaverryan

    So glad you asked :). Yes, definitely June, hopefully early. I've already coded it up and will start recording soon (just need to get forms and Symfony REST part 5 out the door first).

  • 2016-05-15 Raphael Schubert

    Any scheduled date to this tutorial??

  • 2016-03-29 weaverryan

    I have a few other tutorials scheduled before this one, so it won't be in April :/. BUT, *very* soon, we'll be releasing the new Symfony REST course about security, and I think you might be able to use some good things from it :).

    If you hit the "Notify me" button at the top - we'll send you a one-time email when this course comes out.


  • 2016-03-27 Damir Rama

    Hi Ryan, can you tell me when this tutorials come out? Thx for the work. It's greeeat!

  • 2016-03-24 cool

    Looking forward to this tutorial

  • 2016-03-21 weaverryan

    Aaawesome :)

  • 2016-03-21 Yuriy Stenin

    Hi, thanks for your great courses. I've been inspired your courses and creates own simple app for blogging I Am beginner in symfony

  • 2016-02-25 Léo Li


  • 2016-01-13 Felipe Martins

    Nice Ryan!
    I'm looking forward to watching that serie in the next.. :)