From 0a244fd15618b42e9b75ee62f4336166c99e932e Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Sun, 16 Feb 2020 12:21:02 +0100 Subject: [PATCH 1/4] [Security] Various minor fixes in XML config --- security/custom_authentication_provider.rst | 4 +- security/entity_provider.rst | 5 ++- security/force_https.rst | 4 +- security/guard_authentication.rst | 31 ++++++++------- security/json_login_setup.rst | 4 +- security/ldap.rst | 44 +++++++++++---------- security/multiple_guard_authenticators.rst | 2 +- security/multiple_user_providers.rst | 1 - security/remember_me.rst | 6 ++- security/user_checkers.rst | 8 ++-- 10 files changed, 57 insertions(+), 52 deletions(-) diff --git a/security/custom_authentication_provider.rst b/security/custom_authentication_provider.rst index 9b9b83edc61..391635ec5a8 100644 --- a/security/custom_authentication_provider.rst +++ b/security/custom_authentication_provider.rst @@ -172,7 +172,7 @@ the value returned for the expected WSSE information, creates a token using that information, and passes the token on to the authentication manager. If the proper information is not provided, or the authentication manager throws an :class:`Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException`, -a 403 Response is returned. +a 401 Response is returned. .. note:: @@ -188,7 +188,7 @@ a 403 Response is returned. Returning prematurely from the listener is relevant only if you want to chain authentication providers (for example to allow anonymous users). If you want - to forbid access to anonymous users and have a nice 403 error, you should set + to forbid access to anonymous users and have a 404 error, you should set the status code of the response before returning. The Authentication Provider diff --git a/security/entity_provider.rst b/security/entity_provider.rst index 0e3573776e8..a46c00e4877 100644 --- a/security/entity_provider.rst +++ b/security/entity_provider.rst @@ -246,9 +246,10 @@ the username and then check the password (more on passwords in a moment): - + + diff --git a/security/force_https.rst b/security/force_https.rst index 65d5138ed56..25ed6e079f8 100644 --- a/security/force_https.rst +++ b/security/force_https.rst @@ -33,7 +33,7 @@ to use HTTPS then you could use the following configuration: - + @@ -83,7 +83,7 @@ role: diff --git a/security/guard_authentication.rst b/security/guard_authentication.rst index 14159a25cc0..7b40f9898aa 100644 --- a/security/guard_authentication.rst +++ b/security/guard_authentication.rst @@ -116,7 +116,7 @@ Next, make sure you've configured a "user provider" for the user: - + @@ -133,6 +133,7 @@ Next, make sure you've configured a "user provider" for the user: 'your_db_provider' => [ 'entity' => [ 'class' => 'AppBundle:User', + 'property' => 'apiKey', ], ], ], @@ -187,21 +188,18 @@ This requires you to implement several methods:: */ public function getCredentials(Request $request) { - return [ - 'token' => $request->headers->get('X-AUTH-TOKEN'), - ]; + return $request->headers->get('X-AUTH-TOKEN'); } public function getUser($credentials, UserProviderInterface $userProvider) { - $apiKey = $credentials['token']; - - if (null === $apiKey) { + if (null === $credentials) { + // The token header was empty, authentication fails with 401 return; } - // if a User object, checkCredentials() is called - return $userProvider->loadUserByUsername($apiKey); + // if a User is returned, checkCredentials() is called + return $userProvider->loadUserByUsername($credentials); } public function checkCredentials($credentials, UserInterface $user) @@ -222,13 +220,14 @@ This requires you to implement several methods:: public function onAuthenticationFailure(Request $request, AuthenticationException $exception) { $data = [ + // you may ant to customize or obfuscate the message first 'message' => strtr($exception->getMessageKey(), $exception->getMessageData()) // or to translate this message // $this->translator->trans($exception->getMessageKey(), $exception->getMessageData()) ]; - return new JsonResponse($data, Response::HTTP_FORBIDDEN); + return new JsonResponse($data, Response::HTTP_UNAUTHORIZED); } /** @@ -303,11 +302,11 @@ Finally, configure your ``firewalls`` key in ``security.yml`` to use this authen - - + + + + AppBundle\Security\TokenAuthenticator @@ -336,6 +335,8 @@ Finally, configure your ``firewalls`` key in ``security.yml`` to use this authen TokenAuthenticator::class, ], ], + // if you want, disable storing the user in the session + // 'stateless' => true, // ... ], ], diff --git a/security/json_login_setup.rst b/security/json_login_setup.rst index e5945671058..b62f07c1d6e 100644 --- a/security/json_login_setup.rst +++ b/security/json_login_setup.rst @@ -184,8 +184,8 @@ The security configuration should be: + username-path="security.credentials.login" + password-path="security.credentials.password"/> diff --git a/security/ldap.rst b/security/ldap.rst index 2b73e3a9f3b..35e82dcced3 100644 --- a/security/ldap.rst +++ b/security/ldap.rst @@ -152,20 +152,19 @@ use the ``ldap`` user provider. - + .. code-block:: php + // app/config/security.php use Symfony\Component\Ldap\Ldap; $container->loadFromExtension('security', [ @@ -358,15 +357,15 @@ Configuration example for form login - + .. code-block:: php + // app/config/security.php use Symfony\Component\Ldap\Ldap; $container->loadFromExtension('security', [ @@ -394,9 +393,8 @@ Configuration example for HTTP Basic firewalls: main: - # ... + stateless: true http_basic_ldap: - # ... service: Symfony\Component\Ldap\Ldap dn_string: 'uid={username},dc=example,dc=com' @@ -411,23 +409,28 @@ Configuration example for HTTP Basic https://symfony.com/schema/dic/services/services-1.0.xsd"> + + - + .. code-block:: php + // app/config/security.php use Symfony\Component\Ldap\Ldap; $container->loadFromExtension('security', [ + // ... + 'firewalls' => [ 'main' => [ 'http_basic_ldap' => [ 'service' => Ldap::class, 'dn_string' => 'uid={username},dc=example,dc=com', - // ... ], 'stateless' => true, ], @@ -449,7 +452,6 @@ Configuration example for form login and query_string main: # ... form_login_ldap: - # ... service: Symfony\Component\Ldap\Ldap dn_string: 'dc=example,dc=com' query_string: '(&(uid={username})(memberOf=cn=users,ou=Services,dc=example,dc=com))' @@ -466,10 +468,10 @@ Configuration example for form login and query_string - + + @@ -482,11 +484,11 @@ Configuration example for form login and query_string $container->loadFromExtension('security', [ 'firewalls' => [ 'main' => [ + // ... 'form_login_ldap' => [ 'service' => Ldap::class, 'dn_string' => 'dc=example,dc=com', 'query_string' => '(&(uid={username})(memberOf=cn=users,ou=Services,dc=example,dc=com))', - // ... ], ], ] diff --git a/security/multiple_guard_authenticators.rst b/security/multiple_guard_authenticators.rst index 08486591eb5..b9f7622db17 100644 --- a/security/multiple_guard_authenticators.rst +++ b/security/multiple_guard_authenticators.rst @@ -68,7 +68,7 @@ This is how your security configuration can look in action: 'default' => [ 'anonymous' => null, 'guard' => [ - 'entry_point' => '', + 'entry_point' => LoginFormAuthenticator::class, 'authenticators' => [ LoginFormAuthenticator::class, FacebookConnectAuthenticator::class, diff --git a/security/multiple_user_providers.rst b/security/multiple_user_providers.rst index f228d0839a1..56ecaee6976 100644 --- a/security/multiple_user_providers.rst +++ b/security/multiple_user_providers.rst @@ -149,7 +149,6 @@ the first provider is always used: 'pattern' => '^/', 'provider' => 'user_db', 'http_basic' => [ - // ... 'realm' => 'Secured Demo Area', 'provider' => 'in_memory', ], diff --git a/security/remember_me.rst b/security/remember_me.rst index 698b53f4f57..8258e6a2408 100644 --- a/security/remember_me.rst +++ b/security/remember_me.rst @@ -348,7 +348,7 @@ service you just created: @@ -357,6 +357,8 @@ service you just created: .. code-block:: php // app/config/security.php + use Symfony\Bridge\Doctrine\Security\RememberMe\DoctrineTokenProvider; + $container->loadFromExtension('security', [ // ... @@ -365,7 +367,7 @@ service you just created: // ... 'remember_me' => [ // ... - 'token_provider' => 'Symfony\Bridge\Doctrine\Security\RememberMe\DoctrineTokenProvider', + 'token_provider' => DoctrineTokenProvider::class, ], ], ], diff --git a/security/user_checkers.rst b/security/user_checkers.rst index e32bc547acd..97f215bac82 100644 --- a/security/user_checkers.rst +++ b/security/user_checkers.rst @@ -89,8 +89,9 @@ is the service id of your user checker: - - AppBundle\Security\UserChecker + @@ -99,11 +100,10 @@ is the service id of your user checker: .. code-block:: php // app/config/security.php - - // ... use AppBundle\Security\UserChecker; $container->loadFromExtension('security', [ + // ... 'firewalls' => [ 'main' => [ 'pattern' => '^/', From bdccc330fd6adda34ec46fcee83438797382f14f Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Sat, 15 Feb 2020 10:05:49 +0100 Subject: [PATCH 2/4] [Security] renamed memory provider --- security.rst | 117 ++++++++++++++++++++++----- security/multiple_user_providers.rst | 48 +++++------ 2 files changed, 122 insertions(+), 43 deletions(-) diff --git a/security.rst b/security.rst index 9b75df1e8e5..c5c5e4fbcb8 100644 --- a/security.rst +++ b/security.rst @@ -45,7 +45,7 @@ configuration looks like this: # app/config/security.yml security: providers: - in_memory: + users_in_memory: memory: ~ firewalls: @@ -55,6 +55,7 @@ configuration looks like this: main: anonymous: ~ + provider: users_in_memory .. code-block:: xml @@ -67,7 +68,7 @@ configuration looks like this: https://symfony.com/schema/dic/services/services-1.0.xsd"> - + @@ -77,6 +78,7 @@ configuration looks like this: + users_in_memory @@ -86,7 +88,7 @@ configuration looks like this: // app/config/security.php $container->loadFromExtension('security', [ 'providers' => [ - 'in_memory' => [ + 'users_in_memory' => [ 'memory' => null, ], ], @@ -97,6 +99,7 @@ configuration looks like this: ], 'main' => [ 'anonymous' => null, + 'provider' => 'users_in_memory' ], ], ]); @@ -315,7 +318,7 @@ provider, but it's better to think of it as an "in configuration" provider: # app/config/security.yml security: providers: - in_memory: + users_in_memory: memory: users: ryan: @@ -324,7 +327,11 @@ provider, but it's better to think of it as an "in configuration" provider: admin: password: kitten roles: 'ROLE_ADMIN' - # ... + + firewalls: + main: + provider: users_in_memory + # ... .. code-block:: xml @@ -337,13 +344,16 @@ provider, but it's better to think of it as an "in configuration" provider: https://symfony.com/schema/dic/services/services-1.0.xsd"> - + - + + users_in_memory + + @@ -352,7 +362,7 @@ provider, but it's better to think of it as an "in configuration" provider: // app/config/security.php $container->loadFromExtension('security', [ 'providers' => [ - 'in_memory' => [ + 'users_in_memory' => [ 'memory' => [ 'users' => [ 'ryan' => [ @@ -367,13 +377,17 @@ provider, but it's better to think of it as an "in configuration" provider: ], ], ], - // ... + 'firewalls' => [ + 'main' => [ + 'provider' => 'users_in_memory', + ], + ], ]); Like with ``firewalls``, you can have multiple ``providers``, but you'll -probably only need one. If you *do* have multiple, you can configure which +probably only need one. If you *do* have multiple, you have to configure which *one* provider to use for your firewall under its ``provider`` key (e.g. -``provider: in_memory``). +``provider: users_in_memory``). .. seealso:: @@ -421,20 +435,22 @@ To fix this, add an ``encoders`` key: .. code-block:: php // app/config/security.php + use Symfony\Component\Security\Core\User\User; + $container->loadFromExtension('security', [ // ... 'encoders' => [ - 'Symfony\Component\Security\Core\User\User' => 'plaintext', + User::class => 'plaintext', ], // ... ]); -User providers load user information and put it into a ``User`` object. If -you :doc:`load users from the database ` +User providers load user information and put it into a :class:`Symfony\\Component\\Security\\Core\\User\\UserInterface` +implementation. If you :doc:`load users from the database ` or :doc:`some other source `, you'll -use your own custom User class. But when you use the "in memory" provider, -it gives you a ``Symfony\Component\Security\Core\User\User`` object. +use your own custom User class. But when you use the "in memory" provider type, +it gives you a :class:`Symfony\\Component\\Security\\Core\\User\\User` object. Whatever your User class is, you need to tell Symfony what algorithm was used to encode the passwords. In this case, the passwords are just plaintext, @@ -449,6 +465,67 @@ you who you are and what roles you have: Because this URL requires ``ROLE_ADMIN``, if you had logged in as ``ryan``, this would deny you access. More on that later (:ref:`security-authorization-access-control`). +.. tip:: + + If you have many providers and want to define the same encoder for all of + them, you can configure as follow: + + .. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + encoders: + Symfony\Component\Security\Core\User\UserInterface: bcrypt + + # is equivalent to: + AppBundle\Entity\User: bcrypt + Symfony\Component\Security\Core\User\User: bcrypt + # and any other type you may add in the future + # ... + + .. code-block:: xml + + + + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + use Symfony\Component\Security\Core\User\UserInterface; + + $container->loadFromExtension('security', [ + 'encoders' => [ + UserInterface::class => 'bcrypt', + + // is equivalent to: + AppBundle\Entity\User::class => 'bcrypt', + Symfony\Component\Security\Core\User\User::class => 'bcrypt', + // and any other type you may add in the future + ], + // ... + ]); + Loading Users from the Database ............................... @@ -502,11 +579,13 @@ is ``bcrypt``: .. code-block:: php // app/config/security.php + use Symfony\Component\Security\Core\User\User; + $container->loadFromExtension('security', [ // ... 'encoders' => [ - 'Symfony\Component\Security\Core\User\User' => [ + User::class => [ 'algorithm' => 'bcrypt', 'cost' => 12, ] @@ -532,7 +611,7 @@ It will give you something like this: # ... providers: - in_memory: + users_in_memory: memory: users: ryan: @@ -571,7 +650,7 @@ It will give you something like this: // ... 'providers' => [ - 'in_memory' => [ + 'users_in_memory' => [ 'memory' => [ 'users' => [ 'ryan' => [ diff --git a/security/multiple_user_providers.rst b/security/multiple_user_providers.rst index f228d0839a1..1331e3bd5d7 100644 --- a/security/multiple_user_providers.rst +++ b/security/multiple_user_providers.rst @@ -20,14 +20,14 @@ a new provider that chains the two together: # app/config/security.yml security: providers: - chain_provider: + users: chain: - providers: [in_memory, user_db] - in_memory: + providers: [users_in_memory, users_in_db] + users_in_memory: memory: users: foo: { password: test } - user_db: + users_in_db: entity: { class: AppBundle\Entity\User, property: username } .. code-block:: xml @@ -41,20 +41,20 @@ a new provider that chains the two together: https://symfony.com/schema/dic/services/services-1.0.xsd"> - + - in_memory - user_db + users_in_memory + users_in_db - + - + @@ -67,19 +67,19 @@ a new provider that chains the two together: $container->loadFromExtension('security', [ 'providers' => [ - 'chain_provider' => [ + 'users' => [ 'chain' => [ 'providers' => ['in_memory', 'user_db'], ], ], - 'in_memory' => [ + 'users_in_memory' => [ 'memory' => [ 'users' => [ 'foo' => ['password' => 'test'], ], ], ], - 'user_db' => [ + 'users_in_db' => [ 'entity' => [ 'class' => User::class, 'property' => 'username', @@ -88,14 +88,14 @@ a new provider that chains the two together: ], ]); -Now, all firewalls that explicitly define ``chain_provider`` as their user -provider will, in turn, try to load the user from both the ``in_memory`` and -``user_db`` providers. +Now, all firewalls that explicitly define ``users`` as their user +provider will, in turn, try to load the user from both the ``users_in_memory`` then +``users_in_db`` providers. .. deprecated:: 3.4 In previous Symfony versions, firewalls that didn't define their user provider - explicitly, used the first existing provider (``chain_provider`` in this + explicitly, used the first existing provider (``users`` in this example). However, auto-selecting the first user provider has been deprecated in Symfony 3.4 and will throw an exception in 4.0. Always define the provider used by the firewall when there are multiple providers. @@ -114,10 +114,10 @@ the first provider is always used: secured_area: # ... pattern: ^/ - provider: user_db + provider: users_in_db http_basic: realm: 'Secured Demo Area' - provider: in_memory + provider: users_in_memory form_login: ~ .. code-block:: xml @@ -131,9 +131,9 @@ the first provider is always used: https://symfony.com/schema/dic/services/services-1.0.xsd"> - + - + @@ -147,11 +147,11 @@ the first provider is always used: 'secured_area' => [ // ... 'pattern' => '^/', - 'provider' => 'user_db', + 'provider' => 'users_in_db', 'http_basic' => [ // ... 'realm' => 'Secured Demo Area', - 'provider' => 'in_memory', + 'provider' => 'users_in_memory', ], 'form_login' => [], ], @@ -159,8 +159,8 @@ the first provider is always used: ]); In this example, if a user tries to log in via HTTP authentication, the authentication -system will use the ``in_memory`` user provider. But if the user tries to -log in via the form login, the ``user_db`` provider will be used (since it's +system will use the ``users_in_memory`` user provider. But if the user tries to +log in via the form login, the ``users_in_db`` provider will be used (since it's the default for the firewall as a whole). If you need to check that the user being returned by your provider is a allowed From a10dab6deeb04f4970b120febf5436b102bdb3c5 Mon Sep 17 00:00:00 2001 From: Tom Van Looy Date: Sat, 15 Feb 2020 22:20:03 +0100 Subject: [PATCH 3/4] Replace deprecated ObjectManager --- doctrine/event_listeners_subscribers.rst | 4 ++-- doctrine/mapping_model_classes.rst | 2 +- form/data_transformers.rst | 1 - form/unit_testing.rst | 2 +- reference/forms/types/entity.rst | 2 +- service_container/parent_services.rst | 2 +- testing/database.rst | 6 +++--- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/doctrine/event_listeners_subscribers.rst b/doctrine/event_listeners_subscribers.rst index 0c26abeec81..d031443ba9c 100644 --- a/doctrine/event_listeners_subscribers.rst +++ b/doctrine/event_listeners_subscribers.rst @@ -105,7 +105,7 @@ a ``postPersist()`` method, which will be called when the event is dispatched:: use AppBundle\Entity\Product; // for Doctrine < 2.4: use Doctrine\ORM\Event\LifecycleEventArgs; - use Doctrine\Common\Persistence\Event\LifecycleEventArgs; + use Doctrine\Persistence\Event\LifecycleEventArgs; class SearchIndexer { @@ -151,8 +151,8 @@ interface and have an event method for each event it subscribes to:: use AppBundle\Entity\Product; use Doctrine\Common\EventSubscriber; // for Doctrine < 2.4: use Doctrine\ORM\Event\LifecycleEventArgs; - use Doctrine\Common\Persistence\Event\LifecycleEventArgs; use Doctrine\ORM\Events; + use Doctrine\Persistence\Event\LifecycleEventArgs; class SearchIndexerSubscriber implements EventSubscriber { diff --git a/doctrine/mapping_model_classes.rst b/doctrine/mapping_model_classes.rst index 792217246e5..5f2715a8c77 100644 --- a/doctrine/mapping_model_classes.rst +++ b/doctrine/mapping_model_classes.rst @@ -116,8 +116,8 @@ Annotations, XML, Yaml, PHP and StaticPHP. The arguments are: instead of the ``SymfonyFileLocator``:: use AppBundle\Model; - use Doctrine\Common\Persistence\Mapping\Driver\DefaultFileLocator; use Doctrine\ORM\Mapping\Driver\XmlDriver; + use Doctrine\Persistence\Mapping\Driver\DefaultFileLocator; // ... private function buildMappingCompilerPass() diff --git a/form/data_transformers.rst b/form/data_transformers.rst index 5ad3d017739..a974993eb15 100644 --- a/form/data_transformers.rst +++ b/form/data_transformers.rst @@ -342,7 +342,6 @@ First, create the custom field type class:: namespace AppBundle\Form; use AppBundle\Form\DataTransformer\IssueToNumberTransformer; - use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; diff --git a/form/unit_testing.rst b/form/unit_testing.rst index aa9966cda3e..c09cb2a9a0c 100644 --- a/form/unit_testing.rst +++ b/form/unit_testing.rst @@ -135,7 +135,7 @@ make sure the ``FormRegistry`` uses the created instance:: namespace Tests\AppBundle\Form\Type; use AppBundle\Form\Type\TestedType; - use Doctrine\Common\Persistence\ObjectManager; + use Doctrine\Persistence\ObjectManager; use Symfony\Component\Form\PreloadedExtension; use Symfony\Component\Form\Test\TypeTestCase; // ... diff --git a/reference/forms/types/entity.rst b/reference/forms/types/entity.rst index 4a731354ff9..59145cc4602 100644 --- a/reference/forms/types/entity.rst +++ b/reference/forms/types/entity.rst @@ -193,7 +193,7 @@ or the short alias name (as shown prior). ``em`` ~~~~~~ -**type**: ``string`` | ``Doctrine\Common\Persistence\ObjectManager`` **default**: the default entity manager +**type**: ``string`` | ``Doctrine\Persistence\ObjectManager`` **default**: the default entity manager If specified, this entity manager will be used to load the choices instead of the ``default`` entity manager. diff --git a/service_container/parent_services.rst b/service_container/parent_services.rst index 31fd839a807..f5002eb90bf 100644 --- a/service_container/parent_services.rst +++ b/service_container/parent_services.rst @@ -12,7 +12,7 @@ you may have multiple repository classes which need the // src/AppBundle/Repository/BaseDoctrineRepository.php namespace AppBundle\Repository; - use Doctrine\Common\Persistence\ObjectManager; + use Doctrine\Persistence\ObjectManager; use Psr\Log\LoggerInterface; // ... diff --git a/testing/database.rst b/testing/database.rst index 4425ad4c3d7..7d5e0b006bc 100644 --- a/testing/database.rst +++ b/testing/database.rst @@ -45,7 +45,7 @@ Suppose the class you want to test looks like this:: namespace AppBundle\Salary; use AppBundle\Entity\Employee; - use Doctrine\Common\Persistence\ObjectManager; + use Doctrine\Persistence\ObjectManager; class SalaryCalculator { @@ -74,8 +74,8 @@ it's easy to pass a mock object within a test:: use AppBundle\Entity\Employee; use AppBundle\Salary\SalaryCalculator; - use Doctrine\Common\Persistence\ObjectManager; - use Doctrine\Common\Persistence\ObjectRepository; + use Doctrine\Persistence\ObjectManager; + use Doctrine\Persistence\ObjectRepository; use PHPUnit\Framework\TestCase; class SalaryCalculatorTest extends TestCase From 670dcfefe292beb67791479630a6957f73093357 Mon Sep 17 00:00:00 2001 From: Abdouni Abdelkarim Date: Mon, 17 Feb 2020 09:21:33 +0100 Subject: [PATCH 4/4] fixing typo --- frontend/encore/simple-example.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/encore/simple-example.rst b/frontend/encore/simple-example.rst index 5937d19a952..87853ccf2e5 100644 --- a/frontend/encore/simple-example.rst +++ b/frontend/encore/simple-example.rst @@ -332,7 +332,7 @@ If you want to only compile a CSS file, that's possible via ``addStyleEntry()``: .. code-block:: javascript - // webpack/config.js + // webpack.config.js Encore // ...