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
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
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.
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?
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.
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)