Reputation: 71
I have Symfony 6.4 app and wanted to add user login for my new entity SuperUser. I've followed the documentation exactly, and the logging in is successful, but when I visit another page or get redirected after, the logged in user is lost. I thought it has to be a session problem, but no matter how I change the session settings that doesn't help, and when I save something into it, it holds there the entire session time, so I know that works correctly. I've even tried creating my own Authenticator and and nothing helps, what is worst, there is absolutely nothing in the logs, or in the profiler, just anything I could bounce off...
The logs:
[2024-09-16T17:27:20.694109+02:00] security.INFO: Authenticator successful! {"token":{"Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken":"UsernamePasswordToken(user=\"tomatom\", roles=\"ROLE_SUPER_ADMIN, ROLE_USER\")"},"authenticator":"Symfony\\Component\\Security\\Http\\Authenticator\\FormLoginAuthenticator"} []
[2024-09-16T17:27:20.696821+02:00] app.DEBUG: Notified event "security.interactive_login" to listener "FOS\UserBundle\EventListener\LastLoginListener::onSecurityInteractiveLogin". {"event":"security.interactive_login","listener":"FOS\\UserBundle\\EventListener\\LastLoginListener::onSecurityInteractiveLogin"} []
[2024-09-16T17:27:20.926611+02:00] app.DEBUG: Notified event "Symfony\Component\Security\Http\Event\LoginSuccessEvent" to listener "Symfony\Component\Security\Http\EventListener\SessionStrategyListener::onSuccessfulLogin". {"event":"Symfony\\Component\\Security\\Http\\Event\\LoginSuccessEvent","listener":"Symfony\\Component\\Security\\Http\\EventListener\\SessionStrategyListener::onSuccessfulLogin"} []
[2024-09-16T17:27:20.926800+02:00] app.DEBUG: Notified event "Symfony\Component\Security\Http\Event\LoginSuccessEvent" to listener "Symfony\Component\Security\Http\EventListener\PasswordMigratingListener::onLoginSuccess". {"event":"Symfony\\Component\\Security\\Http\\Event\\LoginSuccessEvent","listener":"Symfony\\Component\\Security\\Http\\EventListener\\PasswordMigratingListener::onLoginSuccess"} []
[2024-09-16T17:27:20.926905+02:00] security.DEBUG: The "Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator" authenticator set the response. Any later authenticator will not be called {"authenticator":"Symfony\\Component\\Security\\Http\\Authenticator\\FormLoginAuthenticator"} []
[2024-09-16T17:27:21.044256+02:00] doctrine.INFO: Disconnecting [] []
[2024-09-16T17:27:21.146985+02:00] request.INFO: Matched route "admin_company_list". {"route":"admin_company_list","route_parameters":{"_route":"admin_company_list","_controller":"App\\Controller\\CompanyController::index"},"request_uri":"http://127.0.0.5/admin/company/list","method":"GET"} []
[2024-09-16T17:27:21.364243+02:00] security.DEBUG: Checking for authenticator support. {"firewall_name":"admin","authenticators":1} []
[2024-09-16T17:27:21.364393+02:00] security.DEBUG: Checking support on authenticator. {"firewall_name":"admin","authenticator":"Symfony\\Component\\Security\\Http\\Authenticator\\FormLoginAuthenticator"} []
[2024-09-16T17:27:21.364464+02:00] security.DEBUG: Authenticator does not support the request. {"firewall_name":"admin","authenticator":"Symfony\\Component\\Security\\Http\\Authenticator\\FormLoginAuthenticator"} []
[2024-09-16T17:27:21.416471+02:00] security.DEBUG: Access denied, the user is not fully authenticated; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException(code: 403): Access Denied. at /var/www/vendor/symfony/security-http/Firewall/AccessListener.php:87)"} []
Somewhere after the authentication the user is just lost. I've also tried removing any other configuration from my security.yaml:
security:
password_hashers:
App\Entity\SuperUser: 'auto'
# FOS\UserBundle\Model\UserInterface: 'bcrypt'
# Symfony\Component\Security\Core\User\InMemoryUser: 'auto'
providers:
super_user_provider:
entity:
class: App\Entity\SuperUser
property: username
# fos_userbundle:
# id: fos_user.user_provider.username_email
# chain_provider:
# chain:
# providers: [ super_user_provider, fos_userbundle, in_memory ]
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin:
pattern: ^/admin
provider: super_user_provider
stateless: false
# custom_authenticator: App\Security\Authenticator\LoginAuthenticator
form_login:
login_path: admin_login
check_path: admin_login
enable_csrf: false
default_target_path: admin_company_list
logout:
path: admin_logout
# oauth_token:
# pattern: ^/oauth/v2/token
# security: false
# context: shared_context
#
# olicon:
# pattern: ^/olicon
# provider: super_user_provider
# context: shared_context
#
# hs_rest:
# pattern: ^/hs/rest
# provider: hs_rest
# http_basic: ~
#
# fos_user:
# provider: fos_userbundle
# fos_oauth: true
# stateless: false
# lazy: true
#
# api:
# pattern: ^/api
# provider: fos_userbundle
# fos_oauth: true
# stateless: true
#
# graphql:
# pattern: ^/graphql
# provider: fos_userbundle
# fos_oauth: true
# stateless: true
# user_checker: null
#
# main:
# provider: chain_provider
# stateless: false
# fos_oauth: false
# lazy: true
# context: shared_context
role_hierarchy:
ROLE_SUPER_ADMIN: ~
ROLE_ORDER_SELLITEMS: ~
ROLE_SALESMAN: ~
ROLE_SERVER_ADMIN:
- ROLE_ORDER_SHOW
ROLE_PICKING_REQUIRED_NOTE: ~
ROLE_ORDER_GROUP_ONLY_MY: ~
ROLE_CUSTOMER_ONLY_MY: ~
access_control:
# - { path: ^/api, roles: [ IS_AUTHENTICATED_FULLY ] }
# - { path: ^/olicon, roles: [ ROLE_ORDER_SHOW ] }
- { path: '^/admin/login/[a-z]{2}', roles: [ PUBLIC_ACCESS ] }
- { path: ^/admin, roles: [ ROLE_SERVER_ADMIN, IS_AUTHENTICATED_FULLY ] }
# - { path: ^/graphql, roles: [ PUBLIC_ACCESS ] }
# - { path: ^/hs/rest, roles: [ IS_AUTHENTICATED_FULLY ] }
# - { path: '^/[a-z]{2}/registration', roles: [ PUBLIC_ACCESS ] }
# - { path: '^/[a-z]{2}/resetting', roles: [ PUBLIC_ACCESS ] }
As you can see I'm also using FosUserBundle with FOSOAuthServerBundle, but from what I've tried dumping in their onKernelRequest functions etc. there is nothing that should intervene with the Symfony user login - but I have a strong feeling on of these two might be the cause for this, I just cannot find where it's happening.
Configs for these packages:
fos_oauth_server:
db_driver: orm
client_class: App\Entity\OAuth\Client
access_token_class: App\Entity\OAuth\AccessToken
refresh_token_class: App\Entity\OAuth\RefreshToken
auth_code_class: App\Entity\OAuth\AuthCode
service:
user_provider: fos_user.user_provider.username_email
options:
supported_scopes: user
access_token_lifetime: 43200
refresh_token_lifetime: 1209600
services:
fos_oauth_server.client_manager:
class: App\Util\ClientManager
arguments:
- '@App\Repository\ClientRepository'
fos_user:
from_email:
address: '%env(resolve:SENDER_EMAIL_ADDRESS)%'
sender_name: '%env(resolve:SENDER_EMAIL_NAME)%'
db_driver: orm
firewall_name: fos_user
user_class: App\Entity\User
service:
mailer: App\Service\FosMailer
I also have installed NelmioCorsBundle:
nelmio_cors:
defaults:
allow_credentials: false
allow_origin: []
allow_headers: []
allow_methods: []
expose_headers: []
max_age: 0
hosts: []
origin_regex: false
paths:
'^/':
origin_regex: true
allow_origin: ['^http://localhost:[0-9]+']
allow_headers: ['*']
allow_methods: ['POST', 'PUT', 'GET', 'DELETE']
max_age: 3600
hosts: ['^api\.']
Some more code from my app to paint the whole picture:
SuperUser.php:
#[ORM\Table(name: 'super_user')]
#[ORM\Entity(repositoryClass: SuperUserRepository::class)]
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_USERNAME', fields: ['username'])]
class SuperUser implements UserInterface, PasswordAuthenticatedUserInterface
{
...
LoginController.php:
#[Route('/admin/login/{_locale}', name: 'admin_login')]
public function login(AuthenticationUtils $authenticationUtils): Response
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('login/index.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
]);
}
Login form:
<form action="{{ path('admin_login') }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
<label for="username">Jméno:</label>
<input type="text" id="username" name="_username" class="form-control my-1"
value="{{ last_username }}" required>
<label for="password">Heslo:</label>
<input type="password" id="password" name="_password" class="form-control my-1" required>
<input type="hidden" name="_target_path" value="{{ path('admin_company_list') }}">
<button type="submit" class="btn btn-primary float-end my-2">Přihlásit</button>
</form>
Upvotes: 0
Views: 181
Reputation: 71
Turns out the problem was by the security token not being held properly which was caused by this in our services.yaml:
security.token_storage:
class: Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage
Which we added some time before, because of using container to get the security.token_storage from it (another reason to not access container in your apps no more).
Upvotes: 0