Symfony 2 + JMSSecurityExtraBundle: #PreAuthorize('permitAll') doesn't work - symfony

I have a project with / put behind a firewall. However, I want one of my controllers to be "insecure", e.g display its contents regardless of authentication. But whatever I do, the bundle stays secure.
My current approach is:
security.yml:
jms_security_extra:
secure_all_services: true
expressions: true
security:
encoders:
BrokernetGroup\Platea\SecurityBundle\Entity\User:
id: brokernet_group_platea_security.crypt_encoder
role_hierarchy:
providers:
db_users:
entity:
class: BrokernetGroup\Platea\SecurityBundle\Entity\User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login.html$
security: false
protected_area:
pattern: ^/
form_login:
check_path: /login-check.do
login_path: /login.html
logout:
path: /logout.do
target: /
access_control:
Controller skeleton:
<?php
namespace BrokernetGroup\Platea\InfoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\SecurityExtraBundle\Annotation as SE;
/**
* Description of InfoController
*
* #author Gergely Polonkai
*
* #SE\PreAuthorize("permitAll")
*/
class InfoController
{
/**
* #Route("/", name="BrokernetGroupPlateaInfo_homepage", hostnamePattern="{hostname}", requirements={"hostname" = "%www_hostnames%"})
* #Template
*/
public function homepageAction()
{
return array();
}
}

add anonymous: ~ below the protected_area: in your security.yml file for enabling anonymous token

Related

Symfony 6 - JWTRefreshTokenBundle - "Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken" is not a valid entity or mapped super class

I am installing JWTRefreshTokenBundle on a Symfony 6 and PHP 8.1 base
I followed the documentation and I get the following error:
Class "AppEntityRefreshToken" sub class of "Gesdinet\JWTRefreshTokenBundleEntityRefreshToken" is not a valid entity or mapped super class.
I continued to search and tried the following procedure:
https://github.com/markitosgv/JWTRefreshTokenBundle/issues/332
But the result is the same.
What is strange is that in the documentation we have to update our database with the new RefreshToken entity and absolutely nothing happens even when forcing the update
You will find below the different files.
If someone has an idea, I'm interested ! Thanks in advance
-- App\Entity\RefreshToken.php
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken as BaseRefreshToken;
/**
* #ORM\Entity
* #ORM\Table("refresh_tokens")
*/
class RefreshToken extends BaseRefreshToken
{
}
-- security.yaml
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api:
pattern: ^/api/
stateless: true
entry_point: jwt
json_login:
check_path: /api/authentication_token
provider: app_user_provider
username_path: email
password_path: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
jwt: ~
refresh_jwt:
check_path: /api/authentication_refresh
provider: app_user_provider
main:
jwt: ~
-- routes.yaml
json_login:
path: /api/authentication_token
refresh_token:
path: /api/authentication_refresh
-- gesdinet_jwt_refresh_token.yaml
gesdinet_jwt_refresh_token:
refresh_token_class: App\Entity\RefreshToken
I've found a way to solve your issue.
You need to delete your App/Entity/RefreshToken file then you use the Symphony CLI and run
symfony console make:entity // or php bin/console ...
Name the entity RefreshToken and don't add any property
Then delete the repository class that has just been made and go inside the file App/Entity/RefreshToken to make it look like that :
<?php
namespace App\Entity;
use Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken as BaseRefreshToken;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ORM\Table(name: "refresh_tokens")]
class RefreshToken extends BaseRefreshToken
{
}
You can now
symfony console make:migration
then
symfony console d:m:m
It should work like a charm when you ping your login route
EDIT:
Your security.yaml firewalls should look like that:
firewalls:
dev:
pattern: ^/_(profiler|wdt)
security: false
main:
pattern: ^/login
stateless: true
provider: app_user_provider
json_login:
provider: app_user_provider
check_path: /login
username_path: email
password_path: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
logout:
path: /logout
api:
pattern: ^/api
stateless: true
provider: app_user_provider
jwt:
provider: app_user_provider
authenticator: lexik_jwt_authentication.security.jwt_authenticator
api_token_refresh:
pattern: ^/token/refresh
stateless: true
refresh_jwt: ~

Access control for method login does not work in symfony5?

I just recently started learning symfony. I can’t restrict the access of authorized users to the login method in Symfony5. It continues to work despite restrictions)) This my security.yaml:
security:
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
main:
pattern: ^/api
anonymous: lazy
guard:
authenticators:
- App\Security\LoginAuthenticator
- App\Security\JwtAuthenticator
entry_point: App\Security\LoginAuthenticator
user_checker: App\Security\UserChecker
logout:
path: api_user_logout
success_handler: App\Security\JwtLogoutHandler
delete_cookies:
jwt: { path: /, domain: / }
stateless: false
access_control:
- { path: '^/api/login', roles: IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY }
Controller method:
/**
* #Route("/login", name="login", methods={"POST"})
* #IsGranted("IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY")
*/
public function login()
{
}
/**
* #Route("/logout", name="logout", methods={"GET"})
*/
public function logout()
{
}
/**
* #Route("/user", name="get_user", methods={"GET"})
* #IsGranted("ROLE_USER")
*/
public function getUserData()
{
return $this->json([
'user' => $this->getUser(),
],
Response::HTTP_OK,
[],
[
'groups' => ['api'],
]
);
}
access_control works for everyone except login. #IsGranted ("IS_AUTHENTICATED_ANONYMOUSLY && ! IS_AUTHENTICATED_FULLY") also does not work for my example.
How to restrict authorized users access to login methods?
UPDATED (It would seem - Access denied, but login and logout work.):
security.yaml:
main:
pattern: ^/
anonymous: lazy
guard:
authenticators:
- App\Security\LoginAuthenticator
- App\Security\JwtAuthenticator
entry_point: App\Security\LoginAuthenticator
user_checker: App\Security\UserChecker
logout:
path: api_user_logout
success_handler: App\Security\JwtLogoutHandler
delete_cookies:
jwt: { path: /, domain: / }
stateless: true
access_control:
- { path: '^/', roles: [IS_AUTHENTICATED_FULLY] }
Controller :
/**
* #Route("/login", name="login", methods={"POST"})
* #Security("is_granted('ROLE_USER')", statusCode=403)
*/
public function login()
{
}
/**
* #Route("/logout", name="logout", methods={"GET"})
*/
public function logout()
{
}

Symfony2 after log in says: Authenticated: NO

Authenticated: No appears in the Symfony2 dev toolbar after a successful login.
In my success handler I can access $token->getRoles() and see the role objects assigned to the user so it appears to be serializing okay.
So I'm not sure why it's not authenticating.
Here is my security.yml:
security:
encoders:
FixedApp\Model\User:
algorithm: sha1
encode_as_base64: false
iterations: 1
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_LIMITED_ADMIN]
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
administrators:
entity: { class: FixedApp\Model\User, property: username }
firewalls:
dev:
pattern: ^/(_(profiler|wdt|error)|css|images|js)/
security: false
login:
pattern: ^/$
security: false
secured_area:
pattern: ^/
form_login:
check_path: fixed_app_authentication_login
login_path: fixed_app_homepage
username_parameter: form[username]
password_parameter: form[password]
default_target_path: fixed_app_hub_homepage
always_use_default_target_path: true
success_handler: security.authentication.success_handler
logout:
path: fixed_app_authentication_logout
target: fixed_app_homepage
access_control:
- { path: ^/log-in$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /users/edit, roles: ROLE_ADMIN }
It not authenticating is a problem, because when I go to /users/edit as an admin it says Access Denied. So I need to figure out what is going on here. Any ideas would be most appreciated.
I saw a number of other people online with this same problem but I've never seen a solution put anywhere before - so hopefully this helps someone.
In UserRole.php class I was missing this function:
/**
* #see RoleInterface
*/
public function getRole()
{
return $this->role;
}
And secondly, in User.php class I made it implement EquatableInterface:
use Symfony\Component\Security\Core\User\EquatableInterface;
use Symfony\Component\Security\Core\User\UserInterface;
...
class User implements AdvancedUserInterface, EquatableInterface, \Serializable
{
...
public function isEqualTo(UserInterface $user)
{
if ($this->getId() == $user->getId())
{
return true;
}
else
{
return false;
}
}
And then it started working. The Symfony toolbar button went green, it says Authenticated: Yes and it lists all the roles for that user.

Undefined Method 'findOneBy' when authenticating with symfony2 (as per docs)

I am trying to make a standard login authenticated from the database in symfony2.
I have followed the docs here:
http://symfony.com/doc/current/book/security.html
and here:
http://symfony.com/doc/current/cookbook/security/entity_provider.html
My security File:
security:
encoders:
Acme\UserBundle\Entity\User:
algorithm: sha1
encode_as_base64: false
iterations: 1
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ]
providers:
administrators:
entity: { class: RWLoginBundle:User, property: username }
firewalls:
secured_area:
pattern: ^/
anonymous: ~
form_login: ~
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
My routing file:
login:
pattern: /
defaults: { _controller: RWLoginBundle:Default:login }
login_check:
pattern: /login_check
but when I enter the user and password I get the error:
Fatal error: Call to undefined method RW\LoginBundle\Entity\User::findOneBy() in /var/www/rw/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php on line 55
my login page has been made according to the docs with the form and there is a redirect input there which goes to a url that does exist.
Has anybody come across anything like this before?
Edit: added entity below
namespace RW\LoginBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* RW\LoginBundle\Entity\User
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="RW\LoginBundle\Entity\User")
*/
class User implements UserInterface, \Serializable

Symfony2 login authentication

I'm trying to restrict users from going to anything within /admin/ and if they attempt to then they will be redirected to /login.
At the moment I can get to the login page which is using a traditional login form and if I submit it I get an error returned saying 'Bad Credentials', therefore the /login_check seems to be working correctly. However, if I go to /admin/ or /admin/foo it doesn't redirect to /login. Instead it says 'No route found for GET /admin/'.
My security.yml file is:
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_ADMIN:
ROLE_SUPER_ADMIN:
providers:
administrators:
entity: { class: XXXBundle:AdminUser, property: email }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin_area:
pattern: ^/admin
form_login:
login_path: /login
check_path: /admin/login_check
#anonymous: ~
#http_basic:
# realm: "Secured Demo Area"
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
My routing.yml file is:
login:
pattern: /login
defaults: { _controller: XXXBundleSecurity:login }
login_check:
pattern: /admin/login_check
/admin/XXX routes are unneccessary. If you have set
pattern: ^/admin
/admin/XXX should be redirected to /login.
more details see http://symfony.com/doc/2.0/book/security.html#using-a-traditional-login-form
It seems you're missing both routes you're trying to access. Try to add this to your routing.yml:
admin:
resource: "#XXXBundle/Controller/Admin.php"
type: annotation
prefix: /admin
I like Routes using Annotations very much so I used that in this example.
Then in your Admin.php you can use something like:
// XXXBundle/Controller/Admin.php
namespace XXXBundle/Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
class AdminController extends Controller
{
/**
* #Route("/", name="admin_index")
*/
public function indexAction(Request $request)
{
// Code goes here
}
/**
* #Route("/foo ", name="admin_foo")
*/
public function fooAction(Request $request)
{
// Code goes here
}
}

Resources