Good afternoon. Please i'm using LexikJWTAuthenticationBundle in a symfony 4 api project. I'm using UserProvider for Doctrine.
After Configure Doctrine User Provider, I've install and configure LexikJWTAuthenticationBundle. But when i tried to athentificate using Postman on the url http://localhost:8000/api/login_check whith this JSON {"username":"ak",
"password":"ak"} I've this error: {
"code": 401,
"message": "Bad credentials"
}.
See below my Security.yaml config file. I've read forums to tried to solve this issue but i've not yet found the solution. Can you please help me?
security:
encoders:
App\Entity\Utilisateur:
algorithm: bcrypt
providers:
#in_memory: { memory: ~ }
our_db_provider:
entity:
class: App\Entity\Utilisateur
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/api/login
stateless: true
anonymous: 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
main:
pattern: ^/
user_checker: App\Security\UtilisateurChecker
anonymous: true
provider: our_db_provider
access_control:
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
Have you missed a piece of configuration during installation? I dont see the lexik one:
lexik_jwt_authentication:
secret_key: '%kernel.project_dir%/config/jwt/private.pem' # required for token creation
public_key: '%kernel.project_dir%/config/jwt/public.pem' # required for token verification
pass_phrase: 'your_secret_passphrase' # required for token creation, usage of an environment variable is recommended
token_ttl: 3600
Good morning All. I've found the solution of my problem. In fact, i was typing a bad User Password.
To solve this article, i've used this article https://numa-bord.com/miniblog/symfony-4-les-base-dune-gestion-des-utilisateurs-inscription-connexion-droits-dacces/
I've created au database user by using create user command implemented in the article.
After i have been connected with this previous created user sucessfully. ApiPlatform generate a web tocken for me.
Thank you very much
Related
I use lexik JWT to secure my api and i can login with it.
But the login route works with get and post request when i test with postman.
I want to restrict with POST only.
To do so i tried to add - { path: ^/auth/login_check, roles: PUBLIC_ACCESS, methods:['POST'] } in the access control but it does not do the trick.
I have no error but i still can do get request and have my token back.
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
# used to reload user from session & other features (e.g. switch_user)
# used to reload user from session & other features (e.g. switch_user)
# used to reload user from session & other features (e.g. switch_user)
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api_login:
pattern: ^/auth/login
provider: app_user_provider
stateless: true
json_login:
username_path: email
check_path: /auth/login_check
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api
stateless: true
jwt: ~
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#the-firewall
# 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: ^/auth/login, roles: PUBLIC_ACCESS }
- { path: ^/auth/login_check, roles: PUBLIC_ACCESS, methods:['POST'] }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
So i found the answer myself. The methods option in access_control is a matching option and it does not restrict.
To restrict a route to a specific option, it has to be set in the route like this
#[Route('/my_route', name: 'my_route',methods: ['POST'])]
With Symfony 3.3.16, my users are disconnected in 5/6 minutes. I don't understand.
This problem is only in production (OVH), not in dev.
session.gc_maxlifetime : 1440
security.yml :
security:
encoders:
AppBundle\Entity\User: bcrypt
providers:
database_users:
entity:
class: AppBundle\Entity\User
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
simple_form:
username_parameter: _email
authenticator: AppBundle\Security\Authenticator
check_path: login
login_path: login
success_handler: AppBundle\Handler\AuthenticationSuccessHandler
logout:
path: logout
handlers: [AppBundle\Handler\LogoutHandler]
success_handler: AppBundle\Handler\LogoutSuccessHandler
access_control:
- { path: '^/administration', roles: ROLE_ADMIN }
- { path: '^/user', roles: ROLE_USER }
Can you help me ?
In the symfony configuration reference, you can configure the session lifetime setting:
cookie_lifetime
This determines the lifetime of the session - in seconds. The default
value - null - means that the session.cookie_lifetime value from
php.ini will be used. Setting this value to 0 means the cookie is
valid for the length of the browser session.
gc_maxlifetime
This determines the number of seconds after which data will be seen as "garbage" and potentially cleaned up. Garbage collection may occur during session start and depends on gc_divisor and gc_probability.
Check their value in the config.yml and config_prod.yml
I understand you have already checked the the value of the php.ini value session.gc_maxlifetime
Morning folks,
mainly i want to secure all call against a url that starts with /api/internal.
All endpoints that start with this path are only for internal calls, e.g. in a ajax-search box. So right me when i am wrong but i thought it would be a good idea to secure this via host definition in access_roles
I tried it with the following security.yml
security:
role_hierarchy:
ROLE_myproject_USER: ROLE_USER
ROLE_TEAMMANAGER: ROLE_USER
ROLE_ADMIN: [ROLE_TEAMMANAGER]
providers:
dashboard_users:
ldap:
service: myproject.ldap
# my ldap config
custom_user_provider:
id: myproject.factory.scale_user
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api_internal:
pattern: ^/api/internal
security: true
host: myproject.dev
api_doc:
pattern: ^/api/doc
security: false
api_login:
pattern: ^/api/login
stateless: true
anonymous: true
api:
pattern: ^/api
stateless: true
provider: custom_user_provider
guard:
authenticators:
- myproject.api_login_authenticator
main:
anonymous: ~
form_login_ldap:
login_path: myproject_login
check_path: myproject_login
service: myproject.ldap
dn_string: 'Verbund\{username}'
logout:
path: myproject_logout
target: /
access_control:
- { path: ^/api/internal, host: myproject.dev }
But i get this error:
InvalidConfigurationException in SecurityExtension.php line 481:
No authentication listener registered for firewall "api_internal".
Side information: In this project there a 3 different sections:
/api/internal/**** - should only be accessible from the website itself
/api/ - should be accessible via REST, is secured via JWTToken
the Website itself - is secured via form login and LDAP
Thankful for any help you can provide.
Max
In order to have hosts secured, use access_control
access_control:
# require ROLE_ADMIN for /admin*
- { path: ^/admin, roles: ROLE_ADMIN }
where the path is your desired host.
In order to have everything for a subhost secured use
- { path: ^/admin/*, roles: ROLE_ADMIN }
remove other firewalls than main and dev!
Please refer to http://symfony.com/doc/2.8/security.html for more information
I have been working on setting up the FOSUserBundle/RestBundle/OAuthServerBundle trio to create a headless back end that I can then place a separate front end on top of, and eventually expand to mobile, and possible third party API access. I have the general configuration in place based on the various resources and instructions available and can generate an access token using client credentials.
The application this is being added to is an existing one that uses standard Symfony/Twig for front end/back end interaction and uses FOSUserBundle for authentication.
I have two problems related to the flow of authentication.
I want the user to be able to access some parts of the API without authenticating past the client level, and some parts will require user-level authentication to verify they own the requested resources. I am not finding a way to do this. I've found posts talking about the possibility but nothing giving any direction on how it might be achieved. I believe I'll need to check at the controller level for appropriate access, maybe using custom voters, as checking for 'IS_AUTHENTICATED_FULLY' is coming back as true after just authenticating with the client. I want to be able to programmatically authenticate the user, bypassing the UI login form - that might just be overriding the FOSUserBundle login controller, but I'm not sure.
I either need to create a client without an access token expiration or find a way to implement the refresh token. I don't really see why my own app should need to refresh a token, but if that is the standard way to do it I'm ok with following specs on that.
Below is some relevant code, though by and large the code is pretty box standard stuff copied over from the FOSOAuthServer setup guide.
security.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
oauth_token:
pattern: ^/oauth/v2/token
security: false
rest:
pattern: ^/rest(?!/doc)
fos_oauth: true
stateless: true
anonymous: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
success_handler: security.authentication.success_handler
use_referer: true
logout: true
anonymous: true
access_control:
- { path: ^/rest, roles: [ IS_AUTHENTICATED_FULLY ] }
config.yml snippet
fos_user:
db_driver: orm
firewall_name: main
user_class: AppBundle\Entity\User
registration:
form:
type: AppBundle\Form\Type\RegistrationFormType
profile:
form:
type: user_profile
fos_oauth_server:
db_driver: orm
client_class: AppBundle\Entity\Client
access_token_class: AppBundle\Entity\AccessToken
refresh_token_class: AppBundle\Entity\RefreshToken
auth_code_class: AppBundle\Entity\AuthCode
service:
user_provider: fos_user.user_provider.username_email
options:
supported_scopes: user
fos_rest:
view:
view_response_listener: force
formats:
json: true
templating_formats:
html: true
mime_types:
json: ['application/json', 'application/json;version=1.0', 'application/json;version=1.1']
jpg: ['image/jpeg']
png: ['image/png']
body_listener: true
param_fetcher_listener: true
allowed_methods_listener: true
format_listener:
rules:
- { path: ^/, priorities: [html, json], fallback_format: json, prefer_extension: false }
AD 1)
I solved your problem with two firewalls in security.yml.
Since Symfony is looking first match in security.yml I put first firewall to let anonymous users in:
api_anonym_area:
pattern: (^/api/forgotten-password/.*)
stateless: true
fos_oauth: true
anonymous: true
I catch URL with regex and give anonymous: true
As second firewall I have regex that catches all
api_auth_area:
pattern: ^/
fos_oauth: true
stateless: true
anonymous: false
So in your case, if you want anonymous users to get to /rest/doc, put in front of your firewall:rest something like this:
rest_doc:
pattern: ^/rest/doc
fos_oauth: true
stateless: true
anonymous: true
AD 2)
Its not good practice to have unlimited access token lifetime, but you can do it in config.yml by setting big integer to access_token_lifetime:
fos_oauth_server:
service:
options:
access_token_lifetime: #number in seconds#
To sign in with refresh token just
/oauth/v2/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
its in FOSOAuthServerBundle out of the box
I can't get my firewall rule working correctly. I have a user that has the role D-COMPLIANCEDIALOG, and a firewall rule, that grants access to that rule: - { path: ^/ , roles: D-COMPLIANCEDIALOG }. I still get an access denied (Access denied, the user is neither anonymous, nor remember-me.).
#security.yml
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
providers:
reddot:
id: reddot_user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area:
pattern: ^/
anonymous: ~
http_basic: ~
simple_form:
authenticator: reddot_authenticator
check_path: login_check
login_path: login
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/ , roles: D-COMPLIANCEDIALOG }
User data from symfony profiler:
Username admin
Authenticated? yes
Roles [D-COMPLIANCEDIALOG]
Inherited Roles { }
Token class Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken
What I checked:
The controller has no own security settings
The role name does not seem to have a typo
It is really the last line in the firewall rule, if I remove it, I do have access.
The role name is incorrect. Please check the documentation Security - Roles
All roles you assign to a user must begin with the ROLE_ prefix. Otherwise, they won't be handled by Symfony's security system in the normal way (i.e. unless you're doing something advanced, assigning a role like FOO to a user and then checking for FOO as described below will not work).
I have faced the same issue when entered 'incorrect' role name and was confused by the error message too.
Although Symfony suggest prefixing the roles with ROLE_.. You can still use your custom roles via Securing by an Expression like:
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/ , allow_if: "has_role('D-COMPLIANCEDIALOG')"}