Matys333
Matys333

Reputation: 71

Symfony 6 security user lost after redirect

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

Answers (1)

Matys333
Matys333

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

Related Questions