Symfony - custom firewall setup for API platform - php

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

Related

SF4: multi authenticators with default authenticator

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: ~

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.

Symfony Console command : The token storage contains no authentication token

When I try to launch my custom made Symfony command using php bin/console
I get this bizarre error :
[Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException]
The token storage contains no authentication token. One possible
reason may be that there is no firewall configured for this URL
Its seem that the line responsible is
$user = $em->getRepository('CoreUserBundle:User')->findOneById($deck['user_id']);
if ($user != null)
{
$deck_entity = new Deck();
$deck_entity->SetId($deck['id']);
$deck_entity->SetUser($user);
$deck_entity->SetTitle($deck['titre']);
$deck_entity->SetClass($deck['classe']);
$deck_entity->SetStyle("None");
$deck_entity->SetContentHtml($deck['contenu_html']);
if (isset($deck['contenu_bbcode']))
$deck_entity->SetContentBBCode($deck['contenu_bbcode']);
$deck_entity->SetVideo($deck['video']);
$deck_entity->SetVersion($deck['version']);
$deck_entity->SetIsUpdated($deck['a_jour']);
$deck_entity->SetCraftCost($deck['craft_cout']);
$deck_entity->SetCreationDate(new \DateTime($deck['creation']));
$deck_entity->SetEditionDate(new \DateTime($deck['edition']));
$deck_entity->SetDeckType($deck['deck_type']);
$em->persist($deck_entity);
$metadata = $em->getClassMetaData(get_class($deck_entity));
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
}
UPDATE : Its seem that the error happen at the moment of persisting the entity Deck().
My firewall security are
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
form_login:
login_path: /login
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
remember_me: true
oauth:
resource_owners:
facebook: /login/check-facebook
google: /login/check-google
login_path: /login
failure_path: /login
oauth_user_provider:
service: core.user.user_provider
remember_me:
secret: "%secret%"
name: f1e56d001
lifetime: 604800
httponly: true
domain: xxxx.eu
logout:
path: fos_user_security_logout
handlers: ['sonata.page.cms_manager_selector']
target: /
anonymous: true
switch_user:
role: ROLE_ADMINISTRATOR
parameter: connect_as
I don't understand what I am supposed to, the error seem to tell me that i'm not authenticated, but how since I am using the console ?
Thanks in advance.
after more research, its appear my Deck() entity was triggering a PostPersist event made to create a new thread from the FosCommentBundle, which apparently needed to have the currently logged user to process some stuff (which couldn't get because of the command being a console command ), I could fix the problem by bypassing these event.

Symfony2 security path pattern not working

I've implemented the SimpleSamlPhpBundle in order to authenticate a user on my Symfony application via SAML/Shibboleth.
I modified my security.yml file as follows:
security:
providers:
simplesaml:
id: saxid_user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
saml:
pattern: ^/
anonymous: true
stateless: true
simple_preauth:
authenticator: simplesamlphp.authenticator
provider: simplesaml
logout:
path: /logout
success_handler: simplesamlphp.logout_handler
access_control:
# Make imprint accessible for anonymous access
- { path: ^/imprint$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
As I have an imprint that I want to make accessible for anonymous users, I added the according line to the access_control section.
But this doesn't take effect, if I call example.com/imprint it redirects to the SimpleSAMLphp identity discovery page. Is my pattern wrong? I also tried without the trailing $ character, which didn't help.

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