Symfony can't detect the roles from FOSUser - symfony

I am setting up the user management for a website with FOSUser for the first time and I'm having some trouble figuring out where I mess up.
The role is in the database, in the roles column, like this:
a:1:{i:0;s:10:"ROLE_ADMIN";}
When I do a var_dump($this->getUser()) from the controller, I get this:
(...)
["roles":protected]=> array(1) { [0]=> string(10) "ROLE_ADMIN" }
(...)
So everything's fine over here too.
When I try either if ($this->get('security.context')->isGranted('ROLE_ADMIN')) from the controller or {% if is_granted('ROLE_ADMIN') %} from a twig template, Symfony doesn't detect the role. The profiler also tells me there is only the ROLE_USER role.
Here is my app/config/security.yml file:
security:
providers:
main:
id: fos_user.user_provider.username
encoders:
Site\UserBundle\Entity\User: sha512
role_hierarchy:
ROLE_MODERATOR: [ROLE_USER]
ROLE_ADMIN: [ROLE_MODERATOR]
firewalls:
main:
pattern: ^/
anonymous: true
form_login:
login_path: fos_user_security_login
check_path: fos_user_security_check
logout:
path: fos_user_security_logout
target: /
remember_me:
key: %secret%
default:
anonymous: ~

It looks like you didn't clear the cache. Try to clear cache for your environment
php app/console cache:clear --env=prod #for prod env
or
php app/console cache:clear #for dev env

To help confused passers-by:
In case you have followed the Symfony security tutorial at http://symfony.com/doc/current/security/entity_provider.html#create-your-user-entity, you may have implemented a method like this:
public function getRoles()
{
return array('ROLE_USER');
}
If you have switched to FOSUserBundle later on, you may have forgotten to remove this method. For me, this was the (home-made) issue why my users' roles didn't load properly.

If i am not confuse then you have in your line in security.yml
role_hierarchy:
ROLE_MODERATOR: [ROLE_USER]
ROLE_ADMIN: [ROLE_MODERATOR]
which describe that in both roles you have entered the value
ROLE_USER
so you should do like following lines
role_hierarchy:
ROLE_MODERATOR: [ROLE_USER]
ROLE_ADMIN: [ROLE_ADMIN]
ROLE_SUPER_ADMIN: [ROLE_MODERATOR,ROLE_ADMIN]

Related

Cannot logout with Symfony 4

I cannot logout a user.
I ported custom user management logic over to a Symfony 4 project. It uses recipes for security and guard.
Here is the logout config in my main firewall:
logout:
path: /logout
target: /
Result:
- User goes to /logout
- User is redirected to /
- is_granted("IS_AUTHENTICATED_REMEMBERED") continues to return true in my template (false is expected)
Other Considerations:
- The firewall entry is getting triggered because I get errors if I remove it
- I have tried adding additional parameters to logout to destroy the session and cookies, however that made no difference
- Logging in works fine
Any idea on how to troubleshoot this?
:: edit - added security.yaml as requested ::
security:
encoders:
App\Entity\User: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
app_users:
entity: { class: App\Entity\User, property: email }
app_oauth:
id: app.oauth_user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
provider: app_users
anonymous: ~
oauth:
resource_owners:
google: "/login/check-google"
default_target_path: /
login_path: /
failure_path: /login
oauth_user_provider:
service: app.oauth_user_provider
remember_me:
secret: "%env(APP_SECRET)%"
lifetime: 2592000
path: /
guard:
authenticators:
- App\Security\LoginFormAuthenticator
entry_point: App\Security\LoginFormAuthenticator
logout:
path: /logout
target: /
switch_user: ~
Add these commands
In security.yaml
logout:
path: /logout
target: /
invalidate_session: true
In controller
/**
* #Route("/logout", name="logout")
*/
public function logout()
{
}
In logout button
<a class="text-muted" href="{{ path('logout') }}">logout </a>
Check the serialize and unserialize methods for field $this->email in App\Entity\User.
See my answer to the same problem here
I'll repeat what worked for me:
If you follow the instructions at Symfony Security Logging Out, make sure you use the proper route name to get to /logout. I had to use 'app_logout' to actually get it to logout and I was not able to change that path name in the Security.yaml file without also modifying the controller annotations (see below). No controller needed. No custom handler needed (thank god).
After you configure logout, try running php bin/console debug:router to check the actual route to /logout.
The logout part of my Security.yaml looked like this:
logout:
path: app_logout
# where to redirect after logout
target: front
Based on instructions, I added an empty controller (if you want custom path names, you'll have to change the path names here plus add the change to Security.yaml):
<?php
//App/Controller/SecurityController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class SecurityController extends AbstractController
{
/**
* #Route("/logout", name="app_logout")
*/
public function logout()
{
throw new \Exception('This method can be blank - it will be intercepted by the logout key on your firewall');
}
}
My call looked like this:
<a class="nav-link" href="{{ path('app_logout') }}">Logout</a>
Check your routes with php bin/console debug:router.
For me the security_logout created in the security controller was being called first. I simple removed the function from security controller and it worked (remove the annotation too)

Symfony : Issue with routing

I'm new to Symfony, I follow a tutorial, the part about security and user management but I'm stucked with a problem that seems to come from my routing.
I just created a login form that is actually working, when I go on /app_dev.php/login, the form shows up, I can fill it, but when I submit it, I got the following error :
No route found for "GET /" (from "http://dev-05/ANTOINE/Symfony/web/app_dev.php/login")
404 Not Found - NotFoundHttpException
1 linked Exception:
ResourceNotFoundException ยป
After getting this error, if I go back on the home page, I can see I am connected, so it's working, but the redirection is not .
According to the documentation, this comes from the routing that might be wrongly configured, but I don't know where I made a mistake.
Here's my form, my security.yml and my routing.yml files :
{% extends "AKMUserBundle::layout.html.twig" %}
{% block akmuser_body %}
{% if error %}
<div class="alert alert-danger">{{ error.message }}</div>
{% endif %}
<form action="{{ path('login_check') }}" method="post">
<label for="username">Login : </label>
<input type="text" id="username" name="_username" value="{{ last_username }}" />
<label for="password">Mot de passe :</label>
<input type="password" id="password" name="_password" />
<br />
<input type="submit" value="Connexion" />
</form>
{% endblock %}
security.yml :
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: ['ROLE_USER'] }
admin: { password: adminpass, roles: ['ROLE_ADMIN'] }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
form_login:
login_path: login
check_path: login_check
logout:
path: logout
target: /platform
routing.yml :
akm_platform:
resource: "#AKMPlatformBundle/Resources/config/routing.yml"
prefix: /platform
login:
path: /login
defaults:
_controller: AKMUserBundle:Security:login
login_check:
path: /login_check
logout:
path: /logout
I'm aware that .yml files are very sensitive and need 4 spaces instead of the usual indentation, so I rewrote the files line by line, with the spaces, but it is still not working.
I hope someone can help me :p
If you need some informations don't hesitate!
Edit : Here is my result of the php bin/console debug:router
Edit 2 : To get rid of my problem I just had to add the default_target_path in my security.yml :
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: ['ROLE_USER'] }
admin: { password: adminpass, roles: ['ROLE_ADMIN'] }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
form_login:
login_path: login
check_path: login_check
default_target_path: akm_platform_home
logout:
path: logout
target: /platform
Refresh your cache, console command:php bin/console cache:clear, if you are using older symfony it's app/console instead of bin/console. You can debug your routes with a command: php bin/console debug:router. This is the main system console and in my case I use it on Windows. You must be in the project folder for them to work.
I am not sure where you get redirected to "/", i recently started working in Symfony and most issues were with refreshing cache and wrong yml and route names. However in your case it may be that symfony goes to route / on successful login, you can add default_target_path: your_homepage_route_name or /where_you_want_to_go
it may be what's the issue here.
Since you're new, when you include routes and define a prefix for them, you can easily forget that you set it, which is why router debugging is great since you can see all the info there very easily. When working in symfony always have a console window open if not working in an edior with a built in console. I think JetBeans has it, all of those tutorials are done in it. PS, youtube tutorials for symfony are great, for example Symfony and PHP Programming channel has a good beginner tutorial.

How to create a second form_login to authenticate users

i would like to create a second form_login to authenticate my users but with the same pattern.
here is a part of my security.yml
frontend:
context: frontend
pattern: ^/
form_login:
provider: fos_clientbundle
csrf_provider: form.csrf_provider
login_path : client_login
check_path : client_check
failure_path : null
default_target_path : client_userprofile
form_login:
provider: fos_clientbundle
csrf_provider: form.csrf_provider
login_path : ecommerce_front_checkout
check_path : ecommerce_check
failure_path : null
default_target_path : ecommerce_front_checkout
logout:
path : client_logout
target : client_login
anonymous: true
but it don't work!!
I searched on the web but I have not found solutions.
it would require that users can connect through the main login page and also that it may be on another page like an e-commerce page!!
I hope you can help me.
thank you very much
You could create two different controllers(or Actions) that both extends the BaseSecurityController and just override the renderLogin action(and any other if you need to override some things).
Define both controllers in the routing
routing.yml:
login:
path: /{_locale}/login
defaults: { _controller: ApplicationSonataUserBundle:SecurityFOSUser1:login }
loginForm:
path: /{_locale}/login_frm
defaults: { _controller: ApplicationSonataUserBundle:AnotherSecurityFOSUser1:login }
And then just display the form in a twig:
{% render url('loginForm') %}
i found the solution.it s'very easy!!
in my second form, i must to have add in the default_target_path and failure_path in my form such as :
<input type="hidden" name="_target_path" value="ecommerce_front_checkout" />
<input type="hidden" name="_failure_path" value="ecommerce_front_checkout" />
thank you very much for your help!!

Logged into Sonata admin but authorization checker in controller returns false

I'm working with Symfony CMF, Sonata Admin, Sonata UserBundle, and FOS UserBundle. I can login to the back-end and manage entities for the site. However in my front-end controllers when checking for a logged in user with...
if ( ! $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
exit('not logged in');
}
... the 'not logged in' termination gets fired.
I'm not sure whether I'm using the right method to check the user is authenticated, or whether I have missed something when configuring Sonata UserBundle.
UPDATE (addition of firewalls)
config.yml
# FOS User Bundle
fos_user:
db_driver: orm
firewall_name: main
user_class: Application\Sonata\UserBundle\Entity\User
group:
group_class: Sonata\UserBundle\Entity\BaseGroup
registration:
form:
type: application_sonata_user_registration
security.yml
security:
firewalls:
# -> custom firewall for the admin area of the URL
admin:
pattern: /admin(.*)
form_login:
provider: fos_userbundle
login_path: /admin/login
use_forward: false
check_path: /admin/login_check
failure_path: null
logout:
path: /admin/logout
anonymous: true
# -> end custom configuration
# defaut login area for standard users
main:
pattern: .*
form_login:
provider: fos_userbundle
login_path: /login
use_forward: false
check_path: /login_check
failure_path: null
logout: true
anonymous: true
You have two security systems, when you logged in admin, you're not authenticated in main firewall and vice versa. If you want use multiple firewalls for one session you can use context option http://symfony.com/doc/current/reference/configuration/security.html#firewall-context
Add to each firewall:
context: main

"Remember me" always on in Symfony 2 without configuring it?

I am doing a Admin Panel in Symfony 2. I created the login form, the firewall and the backend controllers and everything runs absolutely fine except the remember me functionality on the site. It is always on whether the checkbox "Remember me" is clicked or not.
Here is my configuration:
**config.yml**
session:
handler_id: ~
cookie_lifetime: 86400
gc_maxlifetime: 1800
**security.yml**
security:
firewalls:
admin_area:
pattern: /admin/
context: admin
anonymous: ~
form_login:
username_parameter: "admin_login[username]"
password_parameter: "admin_login[password]"
csrf_parameter: "admin_login[_token]"
csrf_provider: form.csrf_provider
intention: authentication
login_path: /admin/login
check_path: /admin/login_check
success_handler: admin_login_success_handler
remember_me: true
logout:
path: /admin/logout
target: /admin/
remember_me:
remember_me_parameter: "admin_login[remember_me]"
key: "admin_secret"
lifetime: 86400
path: /admin/
domain: ~
access_control:
- { path: /admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /admin/([a-z_]+)?, roles: ROLE_ADMIN }
The Remember me checkbox:
<input type="checkbox" id="admin_login_remember_me" name="admin_login[remember_me]" value="1">
Am I doing something wrong in this setup so whether the checkbox is selected or not I always get true on running this in the controllers:
$this->get('security.context')->isGranted('IS_AUTHENTICATED_REMEMBERED')
and if I close the browser and reopen it even if "Remember me" was unchecked on the last login I am still logged in the admin panel.
Any comments will be greatly appreciated.
Thanks.

Resources