SF4: multi authenticators with default authenticator - php

I hope that it will be clear. I have a very old application that was upgraded to SF4.4 some time ago and all time is maintained and developed. Unfortunately has a lot of old code. I have to create a firewall that will be supported an old authenticator solution (form_login) and a new one - LexikJWTAuthenticationBundle at the same time. It means that users can get access pages when they have a session or JWT token in headers.
I had this configuration and it works fine:
main:
pattern: '^/'
anonymous: ~
logout_on_user_change: true
form_login:
provider: main
##
remember_me:
##
logout:
##
guard:
provider: main
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
This solution supported the session and JWT token for all endpoints/pages. But unfortunately, I found in /^ places where is used Authorization: Bearer <token> and JWTTokenAuthenticator create some problems and complicate everything. The next thing - it could be dangerous.
So I had to create this solution:
react-api:
pattern: '^/react-api'
anonymous: ~
guard:
provider: main
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
main:
pattern: '^/'
anonymous: ~
logout_on_user_change: true
form_login:
provider: main
#
remember_me:
#
logout:
##
In the current solution for /react-api - I can't authorize via session. Of course, the pattern blocks it. I think it can resolve the problem when I added the default authenticator before/after lexik_jwt_authentication.jwt_token_authenticator which will support the session. Does Symfony have something? Or is another solution?

I found the solution. Symfony docs: https://symfony.com/doc/current/reference/configuration/security.html#firewall-context
I have to change the context for the first firewall:
react-api:
pattern: '^/react-api'
anonymous: ~
context: main
guard:
provider: main
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
main:
pattern: '^/'
anonymous: ~

Related

Symfony - custom firewall setup for API platform

I am trying to restrict access to my Symfony 5.4 application API (running on API platform) by a host (e.g. allow only local network clients). I have this setup, but when accessing the "/api" I am always getting the API plartform (Swagger UI) home page regardles the host IP I am trying it from:
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api:
pattern: ^/api/
stateless: true
provider: app_user_provider
jwt: ~
security: true
host: 127.0.0.1
main:
form_login:
login_path: app_login
check_path: app_login
lazy: true
provider: app_user_provider
logout:
path: app_logout
invalidate_session: true
target: app_login
What I am missing here? It looks like the API platform is "above" the Symfony framework. Does it mean it is not possible to configure security? Or do I have to do it on the HTTP server level?
I want to get the HTTP 403 error when doing the "/api" out of the restricted network area.
set this config for disable docs and entry point
// config/packages/api_platform.yaml
api_platform:
enable_entrypoint: false
enable_docs: false
read more here:
https://api-platform.com/docs/core/configuration/
and here
https://symfonycasts.com/screencast/api-platform-security/production-docs

Symfony user login link in chain user providers

I am creating PasswordLess api for my symfony project by following this: https://symfony.com/doc/5.4/security/login_link.html
I have multiple firewalls:
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
install:
pattern: ^/installer
security: false
anonymous: true
login:
pattern: ^/user/(login|reset-request|send-email|check-email|auto-login)$
provider: chain_provider
anonymous: true
#login_link: # ERROR HERE
# check_route: login_check
# signature_properties: ['id']
main:
pattern: ^/
provider: chain_provider
form_login:
csrf_token_generator: security.csrf.token_manager
check_path: main_security_check
login_path: main_security_login
use_forward: true
logout:
path: main_security_logout
remember_me:
secret: "%env(APP_SECRET)%"
name: BAPRM
lifetime: 1209600 # stay logged for two weeks
samesite: 'lax'
anonymous: false
But when I try to configure it I get this error:
The old authentication system is not supported with login_link.
How can I make it work, what I am missing here.
I am using Symfony 5.4
Thanks.
As mentionned in the documentation you have to enable the new authenticator system to use login links.
Login links are only supported by Symfony when using the authenticator system. Before using this authenticator, make sure you have enabled it with enable_authenticator_manager: true in your security.yaml file.
So modify your security.yaml to add:
enable_authenticator_manager: true
If you do not use it, for example if you use guards, you will have to replace it with the new system.

Unrecognized option "knpu_guard" under "security.firewalls.main" (Symfony)

I would like to add facebook login option to my website. I try to follow this tutorial. But if I add the knpu_guard part under the main section, I get this error:
Unrecognized option "knpu_guard" under "security.firewalls.main"
My firewalls section in the security.yml looks like this:
firewalls:
main:
anonymous: ~
#pattern: ^/
provider: our_db_provider
form_login:
login_path: login
check_path: login
logout:
path: /logout
target: /
knpu_guard:
authenticators:
- app.form_login_authenticator
- app.api_token_authenticator
- app.facebook_authenticator
# by default, use the start() function from FormLoginAuthenticator
entry_point: app.form_login_authenticator
I just added the knpu_guard section, nothing else changed under the firewalls section
I think that the tutorial is a little bit obsolete because knpu_guard is no longer accepted.
You can use guard instead as a key in the security.yml file
Discussion
Try to use this
form_login:
login_path: login
check_path: login
provider: user_provider #where is this provider? It shouldn't be fos_userbundle for example?
anonymous: true

symfony 3 - how to allow unauthenticated access to a URL prefix

Symfony 3.0.3 I want to exclude URLs starting with /document from having to log in
My current security.yml firewalls:
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
docs:
pattern: ^/document
security: false
main:
pattern: ^/
http_basic: ~
provider: our_db_provider
anonymous: ~
form_login:
login_path: /
check_path: login
logout:
path: /logout
target: /
invalidate_session: true
But this results in Error 500 : "The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL." when visiting /document
How is your access_control configuration in security.yml. Shouldn't you allow /document for IS_AUTHENTICATED_ANONYMOUSLY?
access_control:
- { path: ^/document$, role: IS_AUTHENTICATED_ANONYMOUSLY }
In this case, you don't have to define a separate firewall for /document.

Symfony Security: Auth with session or oauth

I have developed a REST API, there are two ways to connect to it: session and oauth.
Basically, my website will use the session mode and third-party softwares will use the oauth mode.
I managed to make make both session and oauth modes to work in symfony, but I can't make them work at the same time.
Here is my firewalls security config:
firewalls:
auth_oauth_token:
pattern: ^/auth/oauth/v2/token
security: false
api:
pattern: ^/api
anonymous: false
fos_oauth: true
stateless: true
auth:
pattern: ^/
anonymous: ~
form_login:
login_path: /auth/session/check
check_path: /auth/session/login
always_use_default_target_path: true
default_target_path: /auth/session/check
failure_path: /auth/session/check
failure_forward: false
use_forward: false
failure_forward: false
username_parameter: username
password_parameter: password
post_only: true
remember_me: false
require_previous_session: false
logout:
path: /auth/session/logout
target: /auth/session/logged_out
invalidate_session: false
Session handling: /auth/session.
OAuth handling: /auth/oauth.
Api: /api.
So, with this config, with "api" firewall first, I can log in with a token.
But even logged in with a session, if I don't specify the token, I won't have access.
With "auth" firewall first, I can log in with the session form.
But even if I specify a token, I won't have access.
I'm getting crazy with this. I found on stack overflow something about chain providers, I would probably need something like "chain firewall"... if forbidden, check another firewall.
Thank you
I solved by duplicating the routes of the api controllers, so that I have a route /api/method which relies on OAuth2, and a /webapi/method route which relies on the standard (main) firewall:
In security.yml:
firewalls:
api:
pattern: ^/api
fos_oauth: true
stateless: true
oauth_token:
pattern: ^/oauth/v2/token
security: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
login_path: /login
check_path: /login_check
logout: true
anonymous: true
access_control:
- { path: ^/api, roles: [ IS_AUTHENTICATED_FULLY ] }
- { path: ^/web-api, roles: [ IS_AUTHENTICATED_FULLY ] }
In routing.yml:
acme_api:
type: rest
prefix: /
resource: "#AcmeBundle/Resources/config/routing_api.yml"
In routing_api.yml:
# REST API - OAUTH Access
acme_api_users:
resource: AcmeBundle\Controller\UsersController
type: rest
defaults: {_format: json}
prefix: /api
name_prefix: api_
# REST API - Frontend Client Access
acme_webapi_users:
resource: AcmeBundle\Controller\UsersController
type: rest
defaults: {_format: json}
prefix: /web-api
name_prefix: webapi_

Categories