Skip to content

[Security] ContextListener misbehavior with multiple UserProviders #4498

Closed
@zeqfreed

Description

@zeqfreed

I'm implementing an application that needs to have separate sets of users for its different sections. For instance, we create Admin and Front sections. For each of the sections I define a firewall rule in security config and a different user provider:

providers:
    provider_admin:
        id: acme.shmundle.my_user_provider.admin

    provider_front:
        id: acme.shmundle.my_user_provider.front

firewalls:
    admin:
         provider: provider_admin
         ....

    front:
         provider: provider_front
         ....

Now, the provider ids reference two different services of the same class that implements UserProviderInterface configured to use different user storages, but same user class.

This setup leads to a problem in ContextListener. After user logs in, the ContextListener attempts to validate user token and refresh user by iterating over every user provider and calling its refreshUser method. If current user provider does not support the user class it throws UnsupportedUserException and ContextListener continues to the next user provider, but if it does and can't actually find the user it throws UsernameNotFoundException which interrupts the iteration and returns null essentially forcing the user to log out.

One solution that would work here is to make sure a different user class used for every user provider, so the iteration always reaches the provider that can refresh user token. But this solution seems quirky, non-obvious and moreover is a kind of side effect depending on the internal implementation of ContextListener.

Another solution is obviously to implement my own ContextListener that will iterate through every user provider regardless of the exceptions thrown. This is the approach I think I will have to take if you confirm that this behavior is actually intended and my use case doesn't lie within symfony's design philosophy.

Please refer to the ContextListener source for the problematic code.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions