gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
With FOSUserBundle setup, the only things we can't do is login and logout. FOSUserBundle does give us a /login
page, but it's just a static HTML form: setting up the actual authentication part is entirely up to us. And that's why, if you try to login now, you get this angry message!
To prove how little FOSUserBundle is doing, go to /login
. If you hover over your web debug toolbar, you can see that the controller behind this page is called SecurityController
. Cool! In my editor, I'll find that file by filename - Shift+Shift in PHP Storm.
Sweet! See loginAction
? This renders the login page. And all it does is check for any authentication errors stored in the session and render a template. It has no logic whatsoever for processing the form submit, logging in, or anything else related to security.
So let's finally add some security goodness, starting with logging out. Right now, if you go to /logout
, you see an error message. This is coming from that same controller: FOSUserBundle gives us a /logout
route, but its controller is never supposed to be called. To fix this, in security.yml
, add logout: ~
. That's it.
... lines 1 - 2 | |
security: | |
... lines 4 - 12 | |
firewalls: | |
... lines 14 - 18 | |
main: | |
... lines 20 - 22 | |
logout: ~ | |
... lines 24 - 31 |
Try going to /logout
again. It works! We are anonymous! By adding the logout
key, Symfony is now waiting for us to go to /logout
. When we do, it intercepts the request and logs us out. Other than giving us the /logout
route, FOSUserBundle has nothing to do with this.
What about logging in? It's the same thing. Under your firewall, add form_login
. That's actually all you need. But, I'll add a bit more: csrf_token_generator: security.csrf.token_manager
. That will make sure the CSRF token - which is already added in the FOSUserBundle login template - is verified when we submit.
... lines 1 - 2 | |
security: | |
... lines 4 - 12 | |
firewalls: | |
... lines 14 - 18 | |
main: | |
... lines 20 - 24 | |
form_login: | |
csrf_token_generator: security.csrf.token_manager | |
... lines 27 - 31 |
As soon as we do that, go to /login
and login with aquanaut1
password turtles
. Winning! We are in! FOSUserBundle gives us a login form, but we need to take care of the rest... which is pretty easy.
Oh, and on the login form, we also have a remember me checkbox. If you want this to work, you'll need to add one more setting: remember_me:
with secret:
'%secret%' to use the secret from parameters.yml
.
... lines 1 - 2 | |
security: | |
... lines 4 - 12 | |
firewalls: | |
... lines 14 - 18 | |
main: | |
... lines 20 - 24 | |
remember_me: | |
secret: '%secret%' | |
... lines 27 - 34 |
Ok, so about 5 lines to get our entire security system working. That kicks butt! And now, we can hook up the login link for real. Open app/Resources/views/base.html.twig
and find the static link. Add an if statement: if is_granted('ROLE_USER')
, then else
and endif
. FOSUserBundle guarantees that every user always at least has ROLE_USER
. So it's safe to use this to figure out whether or not the user is logged in.
<html> | |
... lines 3 - 13 | |
<body> | |
... lines 15 - 19 | |
<header class="header"> | |
... lines 21 - 22 | |
<ul class="navi"> | |
... line 24 | |
{% if is_granted('ROLE_USER') %} | |
... line 26 | |
{% else %} | |
... line 28 | |
{% endif %} | |
</ul> | |
</header> | |
... lines 32 - 50 | |
</body> | |
</html> |
For the logout link, use the route fos_user_security_logout
, then we'll say "Logout". Oh, put all of this stuff inside an li
tag. If you run:
... lines 1 - 19 | |
<header class="header"> | |
... lines 21 - 22 | |
<ul class="navi"> | |
... line 24 | |
{% if is_granted('ROLE_USER') %} | |
<li><a href="{{ path('fos_user_security_logout') }}">Logout</a></li> | |
... lines 27 - 28 | |
{% endif %} | |
</ul> | |
</header> | |
... lines 32 - 53 |
php bin/console debug:router
you can see that this is one of the routes we imported. Use a similar one for login: just copy the logout line, and change it to login.
... lines 1 - 19 | |
<header class="header"> | |
... lines 21 - 22 | |
<ul class="navi"> | |
... line 24 | |
{% if is_granted('ROLE_USER') %} | |
... line 26 | |
{% else %} | |
<li><a href="{{ path('fos_user_security_login') }}">Login</a></li> | |
{% endif %} | |
</ul> | |
</header> | |
... lines 32 - 53 |
Nice! Go back, and refresh. Hit Logout! Woohoo!
Next, let's see what this looks like in the database, and talk about roles.
Hi @Nauman!
In the latest FOSUserBundle, controllers are services. So to override that method, you'll need to override the class of the service. It's not a super common thing to do:
A) Create a class that extends the SecurityController
B) Create a compiler class that changes the fos_user.security.controller
service to use your new class - I'd follow the 2nd example here, where you add the compiler pass to Kernel https://symfony.com/doc/current/service_container/compiler_passes.html
It will probably look something like:
public function process(ContainerBuilder $container): void
{
$container->getDefinition('fos_user.security.controller')->setClass('App\\Controller\\YourNewSecurityController');
}
Good luck!
Hey I'm using Symfony 4 , after adding the "remember_me" setting I got this error "You have requested a non-existent parameter "secret". Did you mean this: "kernel.secret"?"
Thank you !!
Hey @Amina
That's because you haven't defined any "secret" parameter, and you don't have to acutally, in Symfony4 the secret is an environment variable usually named as "APP_SECRET", and you can use it like this:
some_key: '%env(APP_SECRET)%'
Cheers!
Hello , first , I want thank you for this useful tutorial. just a remark to mention. I'm using Symfony 3.4,and in this version I think we should add the provider key in form_login ( security.yml). to let know symfony which provider to use when handling login request/action.
Hey Elmehdi GROLA
If you have a custom provider, then, yes, you have to change the config, but if not, I believe it will just fallback to FOSUserBundle user provider
Cheers!
I am using Symfony 4. My routes for login are working but I don't know why the files haven't been imported to the App folder. Now, I have to edit the files in the vendor/FOS/user-bundle folder. Is this correct or am I missing something.
Hey Ravee s G.
I don't fully get your situation. You won't get any files from the bundle except for a configuration file (and only if the bundle comes with a recipe, I think FOSUserBundle already has a recipe) inside "config/packages". Probably what you are missing is the config line that imports the routes from FOSUserBundle.
Cheers!
Hello Diego, thanks for the reply. I manually imported my twig files to templates/bundles/FOSUserBundle
This is where I copied all my folders like ChangePassword, Profile, Security, etc. from the package. It works now and I can edit those files.
It would be better to use {% if is_granted("IS_AUTHENTICATED_REMEMBERED") %}
instead of relying on if user has ROLE_USER to figure out if user is logged in.
Hey Trashcan4U!
You're right! Well, it depends if you use the "remember_me" functionality :). If you do NOT, then it doesn't make any difference - and so we only talked about ROLE_USER to simplify things. But if you *do* use the remember me functionality, then you're 100% correct - good note!
Cheers!
I have error when i try to log in:
No route found for "GET /" (from "http://localhost/symfony/projects/test2/web/app_dev.php/login")
...when i'm trying logout is similar.
I have this in my security.yml :
form_login: ~
logout: ~
logout:
path: fos_user_security_logout
form_login:
login_path: fos_user_security_login
check_path: fos_user_security_check
csrf_token_generator: security.csrf.token_manager
remember_me:
secret: '%secret%'
Any suggestion?
Hey Szymon,
Do you have a route for "/" URL in your Symfony app? Looks like you just need to declare a route for "/" or probably clear the cache if you have a declared one. You can debug it with:
bin/console debug:router
Cheers!
Hey Victor,
Thx for your answer.
You were right, i didnt have route "/". All my routes started with "/mojaApka/"
Now it works:).
All the best.
No route found for "GET /login/"
I get this error even tho I have :
fos_user:
resource: "@FOSUserBundle/Resources/config/routing/all.xml"
Hey Islam Elshobokshy
That's happening because of the last "slash" in your path, it should be "/login" (without slash)
but if you want to avoid those problems, you can follow this guide and make a redirect to the same route without a slash
http://symfony.com/doc/curr...
Have a nice day!
// composer.json
{
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.3.*", // v3.3.18
"doctrine/orm": "^2.5", // v2.7.0
"doctrine/doctrine-bundle": "^1.6", // 1.10.3
"doctrine/doctrine-cache-bundle": "^1.2", // 1.3.5
"symfony/swiftmailer-bundle": "^2.3", // v2.5.4
"symfony/monolog-bundle": "^2.8", // v2.12.1
"symfony/polyfill-apcu": "^1.0", // v1.3.0
"sensio/distribution-bundle": "^5.0", // v5.0.18
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.25
"incenteev/composer-parameter-handler": "^2.0", // v2.1.2
"knplabs/knp-markdown-bundle": "^1.4", // 1.5.1
"doctrine/doctrine-migrations-bundle": "^1.1", // v1.3.2
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"friendsofsymfony/user-bundle": "^2.0" // v2.0.0
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.1.4
"symfony/phpunit-bridge": "^3.0", // v3.2.7
"nelmio/alice": "^2.1", // v2.3.1
"doctrine/doctrine-fixtures-bundle": "^2.3", // v2.4.1
"symfony/web-server-bundle": "^3.3"
}
}
how to override renderLogin fucntion of fosUserBundle?
I am using symfony 4.4 and I want to pass some data to renderLogin
function. Can you please help me with this? for example, which folder
can I make a controller to extend from Securitycontroller? and do I need
to set route? if yes, how? thank you