I am implementing a simple authenticated area in any Symfony2 project.
Nothing is hard about it, I do not use FOSUserBundle even if I could have, but this is not the problem anyway, my question is really pointing on the security scheme and firewalls.
The basic process :
I can do that quite easily with SF2.
But, I need something that is a bit different on this project :
The firewall does not require any authenticated profile.
It displays additional informations only if an authenticated profile is found, but should be accessible anonymously.
So I would a given page to be the login form page AND a classic firewall page
More informations here :
In fact, the login form page === the firewall home page === the public home page ;
The problem is that on this page, the user is never considered as authenticated, even after log-in with the form, but can access all the privates ^/members pages.
# Security.yml
firewalls:
home:
pattern: ^/$
anonymous: ~
members_area:
pattern: ^/
provider: <any_working_entity-based_provider>
form_login:
login_path: /
check_path: /login_check
post_only: true
default_target_path: /
use_referer: false
logout:
path: /logout
target: /
invalidate_session: false
access_control:
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY } # Public page, login page AND firewall page
- { path: ^/members, roles: ROLE_USER } # Other firewall pages
# My/Super/Bundle/Resources/views/home.html.twig
# [...]
{% if app.user %}
// This part is never displayed, even when the user is successfully authenticated
<h3>Welcome home {{ app.user.username }}</h3>
{% else %}
// This part is always shown...
<form action='{{ path('MySuperBundle_members_login_check') }}' method='post'>
<div>
<label for='_username'>Username</label>
<input type='text' id='_username' name='_username' value='{{ last_username }}' />
</div>
<div>
<label for='_password'>Password</label>
<input type='text' id='_password' name='_password' value='{{ last_username }}' />
</div>
[... CSRF ...]
<div>
<input type='submit' name='submit' value='Submit' />
</div>
</form>
{% endif %}
So finally:
I finally fixed it, I was just confusing firewalls and access control list.
As shown in the question, I had created 2 firewalls on the home page, and in symfony2, you cannot be logged in 2 different firewalls - in no way that I know -
In this case, if you want to have the login form inside any firewall page, you do not manage it with the firewall, but with the access control list.
# Security.yml
firewalls:
members_area:
pattern: ^/
provider: <any_working_entity-based_provider>
anonymous: ~ # To allow unauthenticated users to access the firewall --> The login form
form_login:
login_path: /
check_path: /login_check
post_only: true
default_target_path: /
use_referer: false
logout:
path: /logout
target: /
invalidate_session: false
access_control:
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY } # Public page, login page AND firewall page
- { path: ^/members/suscribe, roles: IS_AUTHENTICATED_ANONYMOUSLY } # Suscribe is a public activity
- { path: ^/members/retrieve_password, roles: IS_AUTHENTICATED_ANONYMOUSLY } # As well as forgotten password
- { path: ^/members/reset_password, roles: IS_AUTHENTICATED_ANONYMOUSLY } # Or reset password features with the token protected page...
- { path: ^/members, roles: ROLE_USER } # BUT, you set up the access control to require any role of the authenticated users, for the different firewall pages