Im building a project with a front app in Angular and a REST API backend in Symfony2 (2.7, needs to move to 3.3 soon).
Backend side, i'm using FOSRestBundle, FOSUSerBundle, LexikAuthBundle and a bunch of other cool bundles for REST API needs.
I recently implemented one time Login through social providers Google and Facebook (front login buttons, then create fos_user backend side and manually set to just recognized user, a JWT provided by LexikBundle). This works well with the following app\config\security.yml:
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_API: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/api/login
stateless: true
anonymous: true
form_login:
check_path: /api/login_check
login_path: /api/login
require_previous_session: false
username_parameter: username
password_parameter: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api
stateless: true
anonymous: true
lexik_jwt:
authorization_header:
enabled: true
prefix: Bearer
query_parameter:
enabled: true
name: bearer
always_authenticate_before_granting: true
access_control:
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/registration., roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: [IS_AUTHENTICATED_FULLY, ROLE_API] }
This works fine for /api/login/social routes (where data is in body, POST), but impossible to reach /api/registration :( :
INFO - Matched route "myapp_security_register".
Context: {"route_parameters": {"_controller":"myapp\\CoreBundle\\Controller\\SecurityController::registerAction","_route":"myapp_security_register"},"request_uri":"http://127.0.0.1:8000/api/registration"}
INFO - Populated the TokenStorage with an anonymous Token.
ERROR - Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: "You do not have the necessary permissions" at C:\projects\myappAPI\vendor\friendsofsymfony\rest-bundle\FOS\RestBundle\EventListener\AccessDeniedListener.php line 70
Context: {"exception":"Object(Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException)"}
I dont get it, because the anonymous token is set ! Why access_control doesnt let /api/registration access my controller ? What am i missing ?
I can also post FOSRestBundle config if it may help.
Thanks, Bor.
There is a typo in your access_control directive:
- { path: ^/api/registration., roles: ['..'] }
... should be
- { path: ^/api/registration, roles: ['..'] }
Related
I have a REST API made with symfony 4.4 and I am having problems in the authentication process.
Everything works fine, but I am experiencing that sometimes the login_check returns 401 Unauthorized with users who days ago could access without problems.
I am using LexikJWTAuthenticationBundle
Security:
security:
role_hierarchy:
ROLE_ADMIN: ROLE_ADMIN
ROLE_MANAGER: ROLE_MANAGER
ROLE_CLIENT: ROLE_CLIENT
ROLE_HOST: ROLE_HOST
encoders:
App\Entity\User:
algorithm: auto
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
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: app.jwt_authenticator_success_handler
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api
anonymous: true
stateless: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
main:
anonymous: ~
logout:
path: app_logout
delete_cookies: ['rhsso']
success_handler: logout_handler
# where to redirect after logout
# target: app_any_route
access_control:
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
I have no idea what is going on. I'm trying to at least log the time where the credentials are verified but I can't find a way to intercept the code for the login_check route. I don't even know where that code is in symfony security.
Any help with this?
Thanks in advance.
/api/login_check path is probably defined in /config/routes/jwt.yaml or somewere in the config/routes...
bin/console debug:router api_login_check
may or may not shed some light
and if you run
bin/console debug:container lexik_jwt_authentication.jwt_token_authenticator
you should find the class to intercept. Perhaps you could dig into the failure handler to find out why you get a 401. Token expiry sounds possible if its happening from time to time.
I have a Symfony 2.8 web app made like an API with FosUserBundle for users entities and Fosoauthserver for authentication.
My security.yml is this:
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
oauth_token:
pattern: ^/oauth/v2/token
security: false
oauth_authorize:
pattern: ^/oauth/v2/auth
form_login:
provider: fos_userbundle
check_path: /oauth/v2/auth_login_check
login_path: /oauth/v2/auth_login
anonymous: true
api:
pattern: ^/v1
fos_oauth: true
stateless: true
switch_user_stateless: true
anonymous: false
access_control:
- { path: ^/v1/register, role: IS_AUTHENTICAIS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/v1/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/v1, role: IS_AUTHENTICATED_FULLY }
I can register an user and login, getting the access_token correctly, but when I try to access to any end point of my API I can access without login.
Even, if I set the right Access token in the headers, if I do $this->getUser() I get null because in any point my app is doing the authentication check.
Any idea? I made differente APIs and never I had this problem.
Thanks!
I encountered a problem on roles promotion in Symfony3, as the title suggests.
The error is simple :
Expression "has_role('ROLE_ADMIN')" denied access.
I promoted the user with
php bin/console fos:user:promote (etc.),
resulting in :
a:1:{i:0;s:10:"ROLE_ADMIN";}
in the database.
I also put an annotation on a my controller method :
/**
* #Security("has_role('ROLE_ADMIN')")
*/
And my security.yml looks like this :
security:
encoders:
MR\UserBundle\Entity\User: sha512
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_MODERATOR]
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
main:
id: fos_user.user_provider.username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main_login:
pattern: ^/login$
anonymous: true
main:
pattern: ^/
anonymous: true
provider: main
form_login:
login_path: fos_user_security_login
check_path: fos_user_security_check
logout:
path: fos_user_security_logout
target: /
remember_me:
secret: %secret%
access_control:
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
Do not bother with the visible increments, there are a mere effect of my copy-paste.
I hope I did not missed an obvious point, but I'd prefer it more than a nothing-solved case.
Thanks in advance
#K.F I "it worked in the morning" => I also had this issue on SF 3.X. It was not a cache problem. Just simply because I had to disconnect and reconnect to appy the new roles to my user.
I know it wasn't your problem but I solved mine after I realized that I made a mistake in my user promotion... I didn't add the ROLE_ADMIN but only ADMIN... rookie mistake
I am trying to set up LexikJWTAuthenticationBundle (Symfony 3) for the first time.
Everything worked smoothly until I tried to make a GET request to an url that was restricted by ROLE_USER.
I can make a POST request to the login_check url, which returns the token, and after that I am trying to make the GET request to the url mentioned above.
I am adding the token on the request headers (Authorization: Bearer ...) and I can see the header being sent on the Google chrome's network tab. However the response always comes back as "401 Unauthorized". I am not sure what I missed here and have been trying to figure this out for days now and searched every forum possible.
Here is my security.yml
security:
user-providers
providers:
db_provider:
entity:
class: ApiBundle:ApiUser
property: email
encoders:
ApiBundle\Entity\ApiUser:
algorithm: bcrypt
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login_check
provider: db_provider
stateless: true
anonymous: true
form_login:
check_path: api_login_check
username_parameter: email
password_parameter: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
require_previous_session: false
api:
pattern: ^/
stateless: true
lexik_jwt:
authorization_header:
enabled: true
prefix: Bearer
query_parameter:
enabled: false
name: bearer
access_control:
- { path: ^/testpage, roles: ROLE_USER }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/login_check, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
Here are the headers being sent
And on My ApiUser.php UserModel I have the getRoles() method implemented like this (for testing):
public function getRoles()
{
return ['ROLE_USER'];
}
Have I missed anything?
After a couple of days reviewing the bundel's code I found that the issue was that the bundle couldn't read the public key, changing the permissions of the file fixed the problem.
In an application I am developing, I'm having a weird issue with the access control for the security component.
I use the FOSUserBundle (of course) for users and I copied the example access control rules from the bundle documentation to my security.yml The login screen (/login) works perfectly but the issue is, all other access control rules have absolutely no effect whatsoever. When a user goes to /register for example, he is redirected to /login, the same goes for /resetting.
This is my security.yml file:
jms_security_extra:
secure_all_services: false
expressions: true
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:
dev:
pattern: ^/(\_(profiler|wdt)|css|images|js)/
security: false
api:
pattern: ^/api
anonymous: false
form_login: false
provider: fos_userbundle
http_basic:
realm: "REST Service Realm"
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
logout: true
anonymous: ~
switch_user: { role: ROLE_SUPER_ADMIN, parameter: _impersonate }
access_control:
- { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/superadmin/, role: ROLE_SUPER_ADMIN }
I have tried to turn of security for paths containing /resetting and /register, but that clearly won't work since the security token still needs to be available for the FOSUserBundle controllers.
Any help would be much appreciated!
It might be to do with the order of the access_control, try putting superadmin above the others. You also don't seem to have a secured_area section (like this example from Symfony2 access control redirects to login)
security:
firewalls:
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: login
check_path: login_check
The problem was that another bundle was messing with each request checking if the user was logged in or not. If the user wasn't logged in, a redirect response was generated to the login page.
No idea why this was done, I think it comes from an era where the original authors had less experience with Symfony.
But so it proves again, always check the logs. Very thoroughly.