Symfony 5 Invalid firewall "api": user provider "app_user_provider" not found - symfony

When i add a new firewall for use api Authentication , i get this fail:
Invalid firewall "api": user provider "app_user_provider" not found.
how i can fix this fail?
security:
encoders:
App\Entity\User:
algorithm: bcrypt
cost: 4
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
in_memory: { memory: ~ }
proveedor:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
form_login:
login_path: login
check_path: login
provider: proveedor
default_target_path: tasks
logout:
path: /logout
target: /
api:
pattern: ^/api
anonymous: lazy
provider: app_user_provider
guard:
authenticators:
- App\Security\TokenAuthenticator

In your firewall named 'api', you specify 'app_user_provider' but in it is not present in the providers list.
In the providers list, you have: in_memory and proveedor.
Try to replace app_user_provider by proveedor.
If the provider allow you to get your user, it should work.

Related

Symfony 5.4 trouble setting up drenso/symfony-oidc-bundle

Im trying to set up an open id connection with this bundle https://github.com/Drenso/symfony-oidc. Did the first step of configuration
drenso_oidc:
#default_client: default # The default client, will be aliased to OidcClientInterface
clients:
default: # The client name, each client will be aliased to its name (for example, $defaultOidcClient)
# Required OIDC client configuration
well_known_url: '%env(OIDC_WELL_KNOWN_URL)%'
client_id: '%env(OIDC_CLIENT_ID)%'
client_secret: '%env(OIDC_CLIENT_SECRET)%'
# Extra configuration options
#redirect_route: '/login_check'
#custom_client_headers: []
# Add any extra client
#link: # Will be accessible using $linkOidcClient
#well_known_url: '%env(LINK_WELL_KNOWN_URL)%'
#client_id: '%env(LINK_CLIENT_ID)%'
#client_secret: '%env(LINK_CLIENT_SECRET)%'
Variables are also set in my .env.
when i enable oidc in my security.yml, this happen :
here's my security.yml :
security:
enable_authenticator_manager: true
password_hashers:
App\Entity\BackUser: auto
App\Entity\FrontUser: auto
providers:
users:
chain:
providers: [back_users, front_users]
back_users:
entity: { class: App\Entity\BackUser, property: username }
front_users:
entity: { class: App\Entity\FrontUser, property: email }
role_hierarchy:
ROLE_SUPER_ADMIN: ROLE_ADMIN
ROLE_ADMIN: [ROLE_REDACTOR, ROLE_ALLOWED_TO_SWITCH]
ROLE_REDACTOR: ROLE_READER
ROLE_READER: ROLE_USER
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
back:
context: global_context
pattern: ^/back
#anonymous: ~
user_checker: App\Security\Checker\UserChecker
provider: back_users
switch_user:
provider: users
role: CAN_SWITCH_USER
form_login:
provider: users
check_path: back_security_login
login_path: back_security_login
#csrf_token_generator: security.csrf.token_manager
enable_csrf: true
default_target_path: back_static_index
success_handler: App\Security\Handler\LoginSuccessHandler
failure_handler: App\Security\Handler\LoginFailureHandler
logout:
path: back_security_logout
target: back_security_login
handlers:
- App\Security\Handler\LogoutHandler
front:
context: global_context
pattern: ^/
oidc: ~
#anonymous: ~
user_checker: App\Security\Checker\UserChecker
provider: front_users
switch_user:
provider: users
role: CAN_SWITCH_USER
# form_login:
# provider: users
# check_path: front_index
# login_path: front_index
# #csrf_token_generator: security.csrf.token_manager
# enable_csrf: true
# default_target_path: front_index
# success_handler: App\Security\Handler\LoginSuccessHandler
logout:
path: front_security_logout
target: front_index
handlers:
- App\Security\Handler\LogoutHandler
I just cant figure out why this happen. If someone has a clue or has already used this package and may know what i'm doing wrong?
wishing y'all a good day

How to Use multiple User Providers in symfony 5. How to chain it?

UPADATED CODE and PROBLEM :
I use symfony Symfony 5.3.6.
I have two kinds of users: company & candidate.
I'd like to make them able to autenticate on their side. 2 forms are coming from front end. ( but for the moment no forms).
I use lexik_jwt_authentication.jwt_token_authenticator to authenticate my both kind of users.
This is the first time I try to code for 2 providers in my security.yaml.
When I had only one , it worked. When i added company, it doesnt anymore.
Here is my updated code in my security.yaml :
security:
# https://symfony.com/doc/current/security/experimental_authenticators.html
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#c-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
App\Entity\Candidate:
algorithm: auto
App\Entity\Company:
algorithm: auto
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
app_candidate_provider:
entity:
class: App\Entity\Candidate
property: email
app_compagny_provider:
entity:
class: App\Entity\Company
property: email
app_users:
chain:
providers: ['app_candidate_provider', 'app_compagny_provider']
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/api/login
stateless: true
anonymous: false
json_login:
check_path: /api/login
username_path: email
password_path: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api/
stateless: true
anonymous: false
provider: app_users
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
main:
# anonymous: lazy
lazy: true
provider: app_user_provider
# 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
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/candidates, roles: IS_AUTHENTICATED_FULLY }
- { path: ^/api/company, roles: IS_AUTHENTICATED_FULLY }
Now, my message error is : "Not configuring explicitly the provider for the "json_login" listener on "login" firewall is ambiguous as there is more than one registered provider.."
i have followed this thread :
Not configuring explicitly the provider for the "guard" listener on "x" firewall is ambiguous as there is more than one registered provider
By remplacing
api:
pattern: ^/api/
stateless: true
anonymous: false
provider: app_users
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
with
api:
pattern: ^/api/
stateless: true
anonymous: false
provider: 'app_candidate_provider'
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
But still doesnt work
Do you have an idea where i make a mistake ?
EDIT : the final answer told by #mcsky is the good one :
security:
# https://symfony.com/doc/current/security/experimental_authenticators.html
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#c-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
App\Entity\Candidate:
algorithm: auto
App\Entity\Company:
algorithm: auto
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
app_candidate_provider:
entity:
class: App\Entity\Candidate
property: email
app_compagny_provider:
entity:
class: App\Entity\Company
property: email
app_users:
chain:
providers: ['app_candidate_provider', 'app_compagny_provider']
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/api/login
stateless: true
provider: app_users
anonymous: false
json_login:
check_path: /api/login
username_path: email
password_path: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api/
stateless: true
anonymous: false
provider: app_users
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
main:
# anonymous: lazy
lazy: true
provider: app_candidate_provider
# 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
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/candidates, roles: IS_AUTHENTICATED_FULLY }
- { path: ^/api/company, roles: IS_AUTHENTICATED_FULLY }
You can't define one user provider with multiple classes as a configuration. It is not designed to work like this. Symfony executes this class Symfony\Bridge\Doctrine\Security\User\EntityUserProvider under the wood, as you can see it work with property and email string only.
So I suggest you define two different user providers, one per class type.
So can you try this configuration?
providers:
app_candidate_provider:
entity:
class: App\Entity\Candidate
property: email
app_compagny_provider:
entity:
class: App\Entity\Company
property: email
app_users:
chain:
providers: ['app_candidate_provider', 'app_compagny_provider']
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/api/login
stateless: true
provider: app_users
anonymous: false
json_login:
check_path: /api/login
username_path: email
password_path: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api/
stateless: true
anonymous: false
provider: app_users
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
Let me know if something isn't clear or don't work

How to fix "The key _username must be a string" error with JWT

I have a website with a standard connection, and I want to add a new way to connect thanks to the API part.
I have followed this doc :
1https://github.com/lexik/LexikJWTAuthenticationBundle/blob/master/Resources/doc/index.md#getting-started
So I add JWT bundle to my Symfony 3 project, and I changed my security.yml :
# app/config/security.yml
security:
encoders:
Symfony\Component\Security\Core\User\User: sha512
GS\UserBundle\Entity\User: sha512 #sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
main:
entity:
class: GS\UserBundle\Entity\User
property: login
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
provider: main
stateless: true
form_login:
login_path: login
check_path: login_check
default_target_path: preLogin
logout:
path: logout
target: preLogin
remember_me:
secret: '%secret%' # se souvenir de moi
lifetime: 1000
always_remember_me: true
login:
pattern: ^/api/login
stateless: true
anonymous: true
provider: main
json_login:
check_path: /api/login_check
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api
stateless: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
access_control:
- { path: /admin, roles: ROLE_ADMIN }
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
I have configured my config.yml like this :
lexik_jwt_authentication:
secret_key: '%kernel.project_dir%/config/jwt/private.pem'
public_key: '%kernel.project_dir%/config/jwt/public.pem'
user_identity_field: login
pass_phrase: 'MY PASSWORD'
token_ttl: 3600
And When I tried to obtain my token with postman like this :
I have this error :
The key "_username" must be a string, "NULL" given.
So, I tried to add "user_parameter" in the security.yml in order to give the parameters name of my user entity, like this :
login:
pattern: ^/api/login
stateless: true
anonymous: true
json_login:
check_path: /api/login_check
username_parameter: login
password_parameter: mdp
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
And now Postman answer me nothing.
EDIT:
I find a commande to check my config file and I have this answer :
And if I remove the username_parameter and the password_parameter, the commande check tell me that the config is ok, but I have the same error with postman :
The key "username" must be a string, "NULL" given.
Help me please I don't find any solution...
Lexik JWT authentication config needs the provider key in the security.yaml.
login:
pattern: ^/api/login
stateless: true
anonymous: true
provider: YOUR_PRODIVER_NAME #in your case it's main
json_login:
check_path: /api/login_check
username_parameter: login
password_parameter: mdp
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
Then to be able to verify the user informations, it needs to know what field is the identity field.
So in the lexik_jwt_authentication.yaml:
lexik_jwt_authentication:
secret_key: '%env(resolve:JWT_SECRET_KEY)%'
public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
pass_phrase: '%env(JWT_PASSPHRASE)%'
user_identity_field: YOUR_USER_FIELD # example email
token_ttl: 7200
About the request parameters, username and password have to be passed (No _)

Symfony 4 : How to have multi providers for user/admin in firewall?

I can not have two different providers for user and admin with two different forms
I want to have two firewalls, for users and for admins. I created two different providers linking two different entities. I can log in as a user, but never as Admin .. I do not understand what I need to add more.
Another thing, I know that there is app.user. But is there also app.admin? In order to have two completely separate accounts on two different firewalls?
security:
providers:
user_provider:
entity:
class: App\Entity\User
property: username
admin_provider:
entity:
class: App\Entity\Admin
property: username
chain_provider:
chain:
providers: [user_provider, admin_provider]
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
provider: user_provider
anonymous: true
logout:
path: /logout
target: /login
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
path: /
form_login:
login_path: /login
check_path: /login
backoffice:
pattern: ^/backoffice
provider: admin_provider
logout:
path: /backoffice/logout
target: /backoffice/login
form_login:
login_path: /backoffice/login
check_path: /backoffice/login
access_control:
- { path: ^/backoffice/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/backoffice, roles: ROLE_ADMIN }
- { path: ^/mon-compte, roles: ROLE_USER }
encoders:
App\Entity\User:
algorithm: bcrypt
cost: 12
App\Entity\Admin:
algorithm: bcrypt
cost: 12
I have null error when I call $authenticationUtils->getLastAuthenticationError()
Switch firewalls order, so the main firewall is the last one.
Symfony uses only one firewall per request and it's the first matched with the pattern. So in your case it's using main firewall for ^/backoffice urls too because /backoffice matches ^/ pattern.
I'm not sure if it will solve all your issues here, but you need to do this in order to really use backoffice firewall.
Regarding app.user and app.admin - no, there's no app.admin. Admin is a user too, so when you'll be logged in as admin, you'll get its entity with app.user
Here is my updated security.yaml :
security:
providers:
admin_provider:
entity:
class: App\Entity\Admin
property: username
user_provider:
entity:
class: App\Entity\User
property: username
chain_provider:
chain:
providers: [user_provider, admin_provider]
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
backoffice:
pattern: ^/backoffice
provider: admin_provider
anonymous: true
logout:
path: admin.logout
target: admin.login
form_login:
login_path: admin.login
check_path: admin.login
default_target_path: admin.index
main:
pattern: ^/
provider: user_provider
anonymous: true
logout:
path: logout
target: login
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
path: /
form_login:
login_path: login
check_path: login
access_control:
- { path: ^/backoffice/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/backoffice, roles: ROLE_ADMIN }
- { path: ^/mon-compte, roles: ROLE_USER }
encoders:
App\Entity\User:
algorithm: bcrypt
cost: 12
App\Entity\Admin:
algorithm: bcrypt
cost: 12

symfony guard authenticator is not being called

I'm working with ldaptools-bundle, fosuserbundle in an api endpoint.
My security.yaml looks like this
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
LdapTools\Bundle\LdapToolsBundle\Security\User\LdapUser: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
chain_provider:
chain:
providers: [ldap, fos_userbundle]
fos_userbundle:
id: fos_user.user_provider.username_email
ldap:
id: ldap_tools.security.user.ldap_user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login
stateless: true
anonymous: true
provider: ldap
json_login:
check_path: /login
username_path: username
password_path: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
guard:
authenticators:
- ldap_tools.security.ldap_guard_authenticator
main:
pattern: ^/
provider: fos_userbundle
stateless: true
anonymous: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
the problem is thath the ldap guard authenticator is not checking the credentials.
When I change the provider to ldap instead fosuser I got a 500 error code in BasePasswordEncoder class, it happens also if I use the chain_provider
Warning: hash_equals(): Expected known_string to be a string, null
given
Is there a miss config or something?
The workflow should be as follow:
The user is authenticated against ldap server
The user is loaded correctly and then lexik takes care of the token generation
Note: The workflow works without ldap and the token is generated.
Thanks in advance!

Resources