Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security][Framework] Use Firewall Settings to get UserProvider Service for Request #54713

Open
Hanmac opened this issue Apr 24, 2024 · 6 comments

Comments

@Hanmac
Copy link
Contributor

Hanmac commented Apr 24, 2024

Description

#46066 Allows to get the Firewall Config for a given Request, but the UserProvider is a string and doesn't give me the Service instance.

What I want, is to get the UserProvider (if able) for the current Firewall.
Either via a Service, or via RequestResolver.

Example:

  • I have a Controller like ForgetPassword.
  • I also have multiple Firewalls with different kind of Users, each should have their own ForgetPasswordAction
  • Instead of Writing multiple Controller Classes, I can just use Routing and have the same Controller under Multiple Routes
  • Now inside the Controller, I would like to access the UserProvider to give me the User I want to do my actions.
  • Depending on the Route, I'm in a different Firewall, so I get a different UserProvider with a different User type.

Example

No response

@n0rbyt3
Copy link
Contributor

n0rbyt3 commented May 5, 2024

Let your controller extend AbstractController, then call $this->getUser() to get the authenticated user if any.

Docs: https://symfony.com/doc/current/controller.html#the-base-controller-class-services

@Hanmac
Copy link
Contributor Author

Hanmac commented May 5, 2024

Let your controller extend AbstractController, then call $this->getUser() to get the authenticated user if any.

Docs: https://symfony.com/doc/current/controller.html#the-base-controller-class-services

The Feature I would like was to get the UserProviderService for the Current Firewall

Not the Current User

@n0rbyt3
Copy link
Contributor

n0rbyt3 commented May 5, 2024

Sorry, my bad. I found a note in the docs:

Sometimes, you need to inject the user provider in another class (e.g. in your custom authenticator). All user providers follow this pattern for their service ID: security.user.provider.concrete.<your-provider-name> (where <your-provider-name> is the configuration key, e.g. app_user_provider).

Source: https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider

@Hanmac
Copy link
Contributor Author

Hanmac commented May 5, 2024

the Problem is still getting the right name/service

For Example A, if the firewall uses multiple Providers, the Firewall Service gets a Chained Provider
Using The Firewall Configuration, i can get the names of the providers, and so their Service Id, but i wouldn't get the Service for the Chained one (that is not that bad imo)

===

Hm i think i found the Service I was looking for: security.user_providers
This one should hold all the UserProvider using their specific ids

@n0rbyt3
Copy link
Contributor

n0rbyt3 commented May 5, 2024

That clarifies a bit more. So you don't want to get the UserProviderInterface service, you want to get inside the internal implementation. And that is impossible.

Your code should not rely on the implementation, but use the interface method it provides.

Let's say you have two firewalls:

  1. "main" that uses a chained provider "chained" which holds provider "in_memory" and "entity" internally
  2. "admin" that uses "ldap" provider directly

You can get access to "chained" or "ldap" by referencing the service, but you cannot determine that "chained" used "entity" internally. Just re-use "chained" as-it and let it iterate through the internal user providers again.

Also I don't see a use-case where you have to use different user providers for different firewalls and cannot rely on chained provider to search for other users.

You may create your own implementation that acts like a chained provider, returns a wrapped UserInterface which holds the source UserProviderInterface service id.

@Hanmac
Copy link
Contributor Author

Hanmac commented May 5, 2024

@n0rbyt3 my goal:

have some UserProvider implement my interface, for example ResetPasswordUserProviderInterface

then i can use the Firewall Config + the security.user_providers service to get the UserProvider
then i can check if that UserProvider does implement my Interface
if it does, then for example, i can call requestPasswordReset and make a new PasswordReset for the given user in that firewall

You can get access to "chained" or "ldap" by referencing the service, but you cannot determine that "chained" used "entity" internally. Just re-use "chained" as-it and let it iterate through the internal user providers again.

that is the problem i am seeing right now, that i don't have a way to access the Chained Provider?
and even if i could, it wouldn't implement my Interface (unless i decorate it?)

Also I don't see a use-case where you have to use different user providers for different firewalls and cannot rely on chained provider to search for other users.

I may not rely on loadUserByIdentifier from the UserProviderInterface

My main Idea was not to have something that can be generated via something like the MakerBundle, but have the router/firewall handle the problem.

example:
/reset-password would detect that it is in the frontend firewall and uses the frontend UserProvider to find the right users
/admin/reset-password then it would detect the admin firewall, and uses the admin UserProvider

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants