Symfony 3 api authentication with FR3DLdapBundle, Jwt and FosUserBundle - api

I'm trying to auth API and BackOffice users of a Symfony 3 app with a combination of 3 bundles : FR3DLdapBundle, LexikJwtAuthBundle and fosUserBundle. the first step I trying to do is to integrate LexicJwtBundle with fosUserBundle as a provider but every time a 401 error "bad credentials " appear to me , here is my config file :
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: en
framework:
#esi: ~
translator: ~
secret: '%secret%'
router:
resource: '%kernel.project_dir%/app/config/routing.yml'
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
default_locale: '%locale%'
trusted_hosts: ~
session:
# https://symfony.com/doc/current/reference/configuration/framework.html#handler-id
handler_id: session.handler.native_file
save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
fragments: ~
http_method_override: true
assets: ~
php_errors:
log: true
# Twig Configuration
twig:
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: "%kernel.project_dir%/var/data/data.sqlite"
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
#path: '%database_path%'
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: '%mailer_transport%'
host: '%mailer_host%'
username: '%mailer_user%'
password: '%mailer_password%'
spool: { type: memory }
lexik_jwt_authentication:
private_key_path: '%jwt_private_key_path%'
public_key_path: '%jwt_public_key_path%'
pass_phrase: '%jwt_key_pass_phrase%'
token_ttl: '%jwt_token_ttl%'
fos_user:
db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
firewall_name: main
user_class: AppBundle\Entity\User
from_email:
address: admin200#tls.tt
sender_name: admin tls
nelmio_cors:
defaults:
allow_credentials: false
allow_origin: []
allow_headers: []
allow_methods: []
expose_headers: []
max_age: 0
hosts: []
origin_regex: false
forced_allow_origin_value: ~
security.yml :
# To get started with security, check out the documentation:
# https://symfony.com/doc/current/security.html
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
# https://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
providers:
in_memory:
memory: ~
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager # Use form.csrf_provider instead for Symfony <2.4
logout: true
anonymous: true
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
#http_basic: ~
# https://symfony.com/doc/current/security/form_login_setup.html
#form_login: ~
login:
pattern: ^/login
stateless: true
anonymous: true
provider: fos_userbundle
form_login:
check_path: /login_check
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
require_previous_session: false
api:
pattern: ^/api
stateless: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
access_control:
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
parameters.yml
# This file is auto-generated during the composer install
parameters:
database_host: 127.0.0.1
database_port: null
database_name: jwt
database_user: root
database_password: root
mailer_transport: smtp
mailer_host: 127.0.0.1
mailer_user: null
mailer_password: null
secret: ea0a3bab6b4dc3bb4b9f8c54c5c7b6e5139ad444
jwt_private_key_path: '%kernel.root_dir%/../var/jwt/private.pem' # ssh private key path
jwt_public_key_path: '%kernel.root_dir%/../var/jwt/public.pem' # ssh public key path
jwt_key_pass_phrase: '' # ssh key pass phrase
jwt_token_ttl: 3600
routing.yml
app:
resource: '#AppBundle/Controller/'
type: annotation
api_login_check:
path: /login_check
# app/config/routing.yml
fos_user_security:
resource: "#FOSUserBundle/Resources/config/routing/security.xml"
fos_user_profile:
resource: "#FOSUserBundle/Resources/config/routing/profile.xml"
prefix: /profile
fos_user_register:
resource: "#FOSUserBundle/Resources/config/routing/registration.xml"
prefix: /register
fos_user_resetting:
resource: "#FOSUserBundle/Resources/config/routing/resetting.xml"
prefix: /resetting
fos_user_change_password:
resource: "#FOSUserBundle/Resources/config/routing/change_password.xml"
prefix: /profile
I'm testing this url : http://localhost:8000/login_check with postman to get the token but nothing work ! some help please ?

you have to send body row by json like that
{"_username":"test",
"_password":"test"}

From the screenshot, it appears you miss the underscore of _username and _password. Maybe that would be enough for the auth to succeed ?

Related

JWT authentication configuration (Symfony 5.3.16)

I have an error 'Unable to create a signed JWT from the given configuration.'
Here is my code.
Security.yaml
security:
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
login:
pattern: ^/api/login
stateless: true
json_login:
username_path: email
check_path: /api/login_check # or api_login_check as defined in config/routes.yaml
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api
stateless: true
jwt: ~
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: app_user_provider
access_control:
- { path: ^/api/login, roles: PUBLIC_ACCESS }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
routes.yaml
api_login_check:
path: /api/login_check
Here are the steps :
symfony new jwt-auth --version=5.3
cd jwt-auth
composer require symfony/maker-bundle --dev
php bin/console doctrine:database:create
composer require orm
composer require security
php bin/console make:user
php bin/console security:hash-password
composer require lexik/jwt-authentication-bundle
php bin/console lexik:jwt:generate-keypair
configure your Security.yaml file
configure your Routes.yaml file
Test API via PostMan
If you can help me it will be great.
Thanks in advance

the symfony security does not protect the route

with symfony, I set up a security system with jwt.
I manage to connect and I get the token.
I configured /api to be protected by token so.
only it doesn't protect it. i can access it in fo
security.yaml
security:
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
App\Entity\User:
algorithm: auto
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
login:
pattern: ^/api/login
stateless: true
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: ~/api, roles: IS_AUTHENTICATED_FULLY }
- { path: ~/auth/register, roles: PUBLIC_ACCESS }
when#test:
security:
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
algorithm: auto
cost: 4 # Lowest possible value for bcrypt
time_cost: 3 # Lowest possible value for argon
memory_cost: 10 # Lowest possible value for argon
#[Route('/api')]
class DataController extends AbstractController
{
#[Route('/locations', name: 'app_locations', methods: 'GET')]
public function locations(LocationRepository $locationRepository): Response
{
GET http://localhost:8001/api/locations
I get the data, but it should not allow me access.
Your access_control seems to be the issue.
Try editing with:
access_control:
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
- { path: ^/auth/register, roles: PUBLIC_ACCESS }
Which should match your /api/locations route.
In your code, you have ~/api which does not match /api/location, that's why we are using ^/api to match anything that follows /api.
You can see more advanced example in the symfony documentation.

Unrecognized field with Symfony 3.4 and flex

I just started a new Symfony 3.4 project with Flex.
I followed the official documentation of FOSOAuthBundle but when I want to create a token /oauth/v2/token I have this error:" Unrecognized field: randomId "
Here are my configuration files:
#config/packages/fos_oauth_server.yaml
fos_oauth_server:
db_driver: orm
client_class: App\Entity\Client
access_token_class: App\Entity\AccessToken
refresh_token_class: App\Entity\RefreshToken
auth_code_class: App\Entity\AuthCode
service:
user_provider: fos_user.user_provider.username
options:
supported_scopes: user
#config/packages/security.yaml
security:
providers:
user_provider:
id: fos_user.user_provider.username
firewalls:
oauth_token:
pattern: ^/oauth/v2/token
security: false
oauth_authorize:
pattern: ^/oauth/v2/auth
security: false
# Add your favorite authentication process here
main:
pattern: ^/
fos_oauth: true
stateless: true
anonymous: false # can be omitted as its default value
access_control:
- { path: ^/, roles: [ IS_AUTHENTICATED_FULLY ] }
#config/packages/doctrine.yaml
parameters:
env(DATABASE_URL): ''
doctrine:
dbal:
# configure these for your database server
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
# With Symfony 3.3, remove the `resolve:` prefix
url: '%env(resolve:DATABASE_URL)%'
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
Do you have an idea?

Symfony User getting disconencted on deployment

Deploying my application on my server, i have issues :
When i log my user manually it works fine, when i go to profile, edit, it works ! !
BUT
WHEN i go to a page non-handled by FOSUserBundle, my user is not logged in anymore ...
$token = new UsernamePasswordToken($user, $user->getPassword(), $providerKey, $user->getRoles());
$userProvider = new UserProvider($this->get('fos_user.user_manager'));
$this->get("security.token_storage")->setToken($token);
$event = new InteractiveLoginEvent($request, $token);
$this->get("event_dispatcher")->dispatch("security.interactive_login", $event);
But in local it's working ....
If you have any idea ... would be glad, thx !!
EDIT :
here is my security.yml
# app/config/security.yml
security:
encoders:
Canapey\UserBundle\Entity\User: sha512
role_hierarchy:
ROLE_USER: [ROLE_USER]
# Un admin hérite des droits d'auteur et de modérateur
ROLE_ADMIN: [ROLE_USER, ROLE_MODERATEUR]
# On garde ce rôle superadmin, il nous resservira par la suite
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
main:
id: fos_user.user_provider.username_email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
provider: main
form_login:
login_path: fos_user_security_login
check_path: fos_user_security_check
csrf_token_generator: security.csrf.token_manager
always_use_default_target_path : true
logout:
path: fos_user_security_logout
target: /
remember_me:
secret: "%secret%" # %secret% est un paramètre de parameter
always_remember_me: true
access_control:
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, roles: IS_AUTHENTICATED_ANONYMOUSLY }
Shortly: get the path of your sessions in config.yml:
framework:
...
session:
...
save_path: ...
and make sure it's not changed / emptied during deploy.
Details
Most deploy systems clean all work folders (e.g. cache, tmp, sessions) during deploy, or even use a release-based structure where the actual root is created from scratch each time and soft-linked to a current directory (see e.g. Capistrano: http://capistranorb.com/documentation/getting-started/structure/).
In these situations, sessions are destroyed during deploy so of course you get logged out.

Two separate login pages in Symfony 2

I'm trying to figure out how to have two separate login pages: a default login for the .com page and one for specific users, for example for the route /special.
Is this easily possible with in one SF2 project?
UPDATE:
I have the following configuration in my firewall (I'm using fosub)
providers:
custom:
id: ib.user_provider
fos_userbundle:
id: fos_user.user_manager
my_fos_facebook_provider:
id: my.facebook.user
firewalls:
special:
pattern: ^/special
form_login:
provider: fos_userbundle
login_path: /special/login
check_path: /special/login_check
use_referer: false
default_target_path: /special
success_handler: ib.login_handler
provider: custom
main:
pattern: ^/.*
form_login:
provider: fos_userbundle
login_path: /login
check_path: /login_check
use_referer: false
default_target_path: /
provider: custom
fos_facebook:
always_use_default_target_path: true
app_url: "http://apps.facebook.com/%facebook_app_id%/"
server_url: "http://aw.com/aw/web/app_dev.php/"
login_path: /login
check_path: /login_check/facebook
default_target_path: /checkFB
success_handler: facebook_auth_success_handler
provider: my_fos_facebook_provider
logout:
#handlers: ["fos_facebook.logout_handler"]
target: /
anonymous: ~
In the ib.login_handler I have the following:
public function onAuthenticationSuccess(Request $request,TokenInterface $token)
{
if ($this->security->isGranted('ROLE_CATEGORIZER'))
{
$response = new RedirectResponse($this->router->generate('MyCoBundle_mailAdmin_index'));
}
return $response;
}
With this configuration if I go to mydomain.com/special I get the following error: Fehler: Umleitungsfehler (in english: Error: Redirection error)
UPDATE:
in chrome I get: No route found for "GET /special/login"
404 Not Found - NotFoundHttpException
1 linked Exception: ResourceNotFoundException »
I don't have a special route for this login path. What I want to achieve is just, that a special user has only access to pages under the path / special.
It's possible, you can define many protected zones => many firewalls.
Let's see this app/config/security.yml configuration to know how :
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
special_area:
pattern: ^/special
anonymous: ~
form_login:
check_path: /special/login_check
login_path: /special/login
logout:
path: /special/logout
target: /
general_area:
pattern: ^
anonymous: ~
form_login:
check_path: /login_check
login_path: /login
logout:
path: /logout
target: /
access_control:
- { path: ^/_internal, role: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/special/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
Beware that special_area must be defined above genereal_area because general_area's pattern matches every other ones...
What you must add in your bundle routing.yml :
_security_login_special:
pattern: /special/login
defaults: { _controller: FOSUserBundle:Security:login }
_security_check_special:
pattern: /special/login_check
_security_logout_special:
pattern: /special/logout
And you have to add another role for general_area, so you need to override FOSUserManager and make it add this supplementary role on user loading... (More information here : https://github.com/FriendsOfSymfony/FOSUserBundle/blob/1.2.0/Resources/doc/user_manager.md)