Symfony 2.5: Authentication fails at every second page call - php

I have updated a symfony 2.0 project to 2.5 and now i am faced with some problems with authentication:
After submitting the username and password i am authenticated. If i follow a link in the secured area or if i am refreshing the current page i get this error:
There is no user provider for user "XXX\AccountBundle\Entity\Worker".
After refreshing again i am authenticated.
After the next refresh i am not.
After refreshing again i am authenticated.
And so on …
This is my security.yml:
security:
encoders:
XXX\AccountBundle\Entity\Worker:
algorithm: sha1
iterations: 1
encode_as_base64: false
role_hierarchy:
ROLE_ACCOUNT_OWNER: [ROLE_USER]
providers:
users:
entity: { class: XXXAccountBundle:Worker, property: email }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
application:
pattern: ^/
anonymous: ~
form_login:
login_path: /login
check_path: /login_check
default_target_path: /dashboard
use_referer: true
remember_me:
key: "%secret%"
lifetime: 31536000 # 365 days in seconds
path: /
domain: ~ # Defaults to the current domain from $_SERVER
logout:
path: /logout
target: /
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
If i remove the "remember me"-section i get logged out after the first request.

Because the authentication problem appeared every second call i had good reasons to check the serializable stuff of the user object. Everything was fine there, but i had to reimplement some custom functions in the UserRepository class where the user is loaded.
Because of the error message i searched for several hours at the wrong place. My security.yml setup was fine.
Now the authentication process works again :)

Related

Why does the "Remember me" functionality in Symfony 5.4 not work (with my setup)

I've a page with form login and "remember me" functionality enabled. Unfortunately the remember me" wont work.
The security panel doesn't show any authenticators. Interestingly after closing the browser and trying to get on the page again, the security panel shows the correct authenticated user, but redirects always to the login page.
Can anybody help?
Here part of my security.yml
security:
enable_authenticator_manager: true
role_hierarchy:
ROLE_SUPPORT: ROLE_USER
ROLE_ADMIN: [ROLE_SUPPORT, ROLE_ALLOWED_TO_SWITCH]
password_hashers:
Symfony\Component\Security\Core\User\User:
algorithm: bcrypt
cost: 12
App\Entity\User:
algorithm: auto
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area:
form_login:
login_path: login
check_path: login
enable_csrf: true
logout:
path: /logout
target: /
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
access_control:
- { path: ^/public, roles: PUBLIC_ACCESS }
- { path: ^/others, roles: IS_AUTHENTICATED_FULLY }
Thx in advance
UPDATE
With lazy: true the security panel now shows authenticators
Unfortunately IS_AUTHENTICATED_REMEMBERED is missing in the access_control section.

login_throttling is ignored if correct username/password

I have added login throttling to my symfony app.
If I try to log in 5 times in a row in the same minute with invalid credentials I have a TooManyLoginAttemptsAuthenticationException in the onAuthenticationFailure method of my authentificator, so far so good.
But if I try to login with correct credentials in the same minute after the TooManyLoginAttemptsAuthenticationException I was expecting to have the same error but I'm actually successfully logged in.
Am I missing Something ?
My security.yaml :
security:
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
ldap:
id: App\Security\LdapUserProvider
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\Utilisateur
property: nni
encoders:
App\Entity\Utilisateur:
algorithm: 'auto'
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
access_control:
- { path: ^/get_team_email$, roles: PUBLIC_ACCESS }
- { path: ^/login$, roles: PUBLIC_ACCESS }
- { path: ^/login_check$, roles: PUBLIC_ACCESS }
- { path: ^, roles: ROLE_USER}
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
security: true
provider: '%connexion_provider%'
entry_point: App\Security\LdapFormAuthenticator
logout:
path: /logout
success_handler: app.logout.success.handler
# configuring the maximum login attempts (per minute)
login_throttling:
max_attempts: 3
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
guard:
authenticators:
- App\Security\LdapFormAuthenticator
form_login:
use_forward: true
login_path: login
check_path: login
As you can see in the source code of the throttling handler, the limiter is reset on successful logins. It solely kicks in on three succeeding failing login attempts (where that 3 has been defined in your own configuration)

Symfony 4 external login check

I've created a basic login form in Symfony 4 like this, which all works fine:
security:
encoders:
App\Entity\User:
algorithm: bcrypt
providers:
backend_user_provider:
entity:
class:
App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
cms:
switch_user: true
pattern: ^/
http_basic: ~
provider: backend_user_provider
anonymous: ~
form_login:
login_path: login
check_path: login_submit
logout:
path: logout
target: login
remember_me:
secret: '%kernel.secret%'
lifetime: 604800
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_BACKEND }
Now, what I'd like to achieve is that if a user doesn't exist, I can make a CURL call to a certain external location (with the email and password), and depending on the JSON result (let's say {success:true} or {success:false}) log in the user anyway.
How do I do this? I know about the Guard component, but I can't seem to figure out how to put it in practice.
Thanks in advance!
You could use ChainUserProvider for that purpose and wire it up together with you ExternalUserProvider.
https://symfony.com/doc/4.0/security/multiple_user_providers.html

Symfony 4 : Anonymous token in public page even after logged in

On my website, I have 3 sections : Admin, Members and Public. The Admin section is only reachable through "gestion.%domain%", and must have an Admin User. This section works great.
For the Members section, it is reachable through "membre.%domain%", and must have a Member User. This also works great.
The problem comes to the Public section. Every part of this section is accessible either anonymously or logged in with a Member User. When logged in, the top menu will change a bit to show more option (kinda like any shopping website).
So I've configured my security settings as follow :
security:
providers:
membre_provider:
id: App\Security\Provider\MembreProvider
manager_provider:
id: App\Security\Provider\ManagerProvider
encoders:
App\Entity\Utilisateur: sha512
role_hierarchy:
ROLE_MEMBRE: [ROLE_NON_MEMBRE]
ROLE_SUPER_ADMIN: [ROLE_ADMIN]
ROLE_ADMIN: [ROLE_EDITEUR]
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin:
host: 'gestion.%domain%'
pattern: .*
anonymous: ~
form_login:
login_path: admin_login
check_path: admin_login
access_denied_url: admin_access_denied
provider: manager_provider
logout:
path: admin_logout
target: admin_login
main:
pattern: .*
anonymous: true
form_login:
login_path: membre_login
check_path: membre_login
access_denied_url: membre_login
provider: membre_provider
user_checker: App\Security\MembreUserChecker
logout:
path: membre_logout
target: index
remember_me:
secret: '%kernel.secret%'
name: 'remember_me_main'
lifetime: 604800 # 1 week in seconds
path: /
always_remember_me: true
access_control:
- { path: ^/connexion, roles: IS_AUTHENTICATED_ANONYMOUSLY, host: 'membre.%domain%' }
- { path: ^/demande_reinitialisation, roles: IS_AUTHENTICATED_ANONYMOUSLY, host: 'membre.%domain%' }
- { path: ^/reinitialisation, roles: IS_AUTHENTICATED_ANONYMOUSLY, host: 'membre.%domain%' }
- { path: ^/, roles: ROLE_NON_MEMBRE, host: 'membre.%domain%'}
- { path: ^/connexion, roles: IS_AUTHENTICATED_ANONYMOUSLY, host: 'gestion.%domain%' }
- { path: ^/, roles: ROLE_EDITEUR, host: 'gestion.%domain%'}
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY}
As you can see, I have the admin context and the main context. The main context is shared between the "Members" section and the "Public" section. And it does work as intended when testing it (in the "Security" tab of the profiler, both shows as "main" context)
The problem is when I try to get the logged in user infos in the public section, I always get the anonymous token (it even shows the anonymous token in the profiler), but when I'm in the "Members" section, I can get the logged in user correctly.
I'm completely lost there...
Ok, so I have managed to solve my issue. The problem came from the session handling. Since I have multiple sub-domains, the session wasn't shared between them, so my public section wasn't aware that the user was logged in in the member section.
The only thing I had to configure was the session parameters in framework.yml :
session:
handler_id: ~
cookie_domain: '.%domain%'
name: 'MYAPPSESSID'
EDIT : This SO answer helped me in finding and solving the problem : https://stackoverflow.com/a/29850083/1907465

Symfony2 access control redirects to login

In an application I am developing, I'm having a weird issue with the access control for the security component.
I use the FOSUserBundle (of course) for users and I copied the example access control rules from the bundle documentation to my security.yml The login screen (/login) works perfectly but the issue is, all other access control rules have absolutely no effect whatsoever. When a user goes to /register for example, he is redirected to /login, the same goes for /resetting.
This is my security.yml file:
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
dev:
pattern: ^/(\_(profiler|wdt)|css|images|js)/
security: false
api:
pattern: ^/api
anonymous: false
form_login: false
provider: fos_userbundle
http_basic:
realm: "REST Service Realm"
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
logout: true
anonymous: ~
switch_user: { role: ROLE_SUPER_ADMIN, parameter: _impersonate }
access_control:
- { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/superadmin/, role: ROLE_SUPER_ADMIN }
I have tried to turn of security for paths containing /resetting and /register, but that clearly won't work since the security token still needs to be available for the FOSUserBundle controllers.
Any help would be much appreciated!
It might be to do with the order of the access_control, try putting superadmin above the others. You also don't seem to have a secured_area section (like this example from Symfony2 access control redirects to login)
security:
firewalls:
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: login
check_path: login_check
The problem was that another bundle was messing with each request checking if the user was logged in or not. If the user wasn't logged in, a redirect response was generated to the login page.
No idea why this was done, I think it comes from an era where the original authors had less experience with Symfony.
But so it proves again, always check the logs. Very thoroughly.

Categories