Symfony/Configure FOSUserBundle login

From Aimeos documentation

Symfony
Other languages:
English 100%


2017.x version

The FOS user bundle is a Symfony component to handle login and registration of users. It's very popular among Symfony developers because it reduces implementing that part of an application to some configuration settings and templates for the look and feel.

There is some documentation for the FOS user bundle that describes the possibilities of the bundle in more detail. Please use it as additional reference especially for the templating stuff and if you need more or different settings according to you requirements.

Register the FOS user bundle

To make the FOS user bundle known to your application, it must be registered in the app/AppKernel.php file of your application:

  1. public function registerBundles()
  2. {
  3.     $bundles = array(
  4.         new FOS\UserBundle\FOSUserBundle(),
  5.         ...
  6.     );
  7.  
  8.     return $bundles;
  9. }

If you foget to do so, you will get this exception telling you that the configuration key "fos_user" is unknown:

There is no extension able to load the configuration for "fos_user" (in .../app/config/config.yml)

Required configuration

Both, for the FOS user bundle as well as the integration into the Aimeos bundle, there are some configuration settings necessary to make things work. These settings need to be added at the end of your app/config/config.yml file.

The configuration for the FOS user bundle must be located beneath the "fos_user" key:

  1. fos_user:
  2.     db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
  3.     user_class: Aimeos\ShopBundle\Entity\FosUser
  4.     firewall_name: aimeos_myaccount
  5.     from_email:
  6.         address: "%mailer_user%"
  7.         sender_name: "%mailer_user%"

The "db_driver" line tells the FOS user bundle to access the user database via the "orm" driver, which uses Doctrine in the backend. To access the properties of the users, the Aimeos bundle contains an user class implementation named "FosUser". That class must be used by the FOS user bundle, which is configured by the "user_class" line. The last thing is the "firewall_name". This setting is especially important because the string used here must match the name in the firewalls block in the "app/config/security.yml" file.

If you forget to set the value for the user_class or firewall_name resp. set "firewall_name" to string whose key is not existing beneath the "firewalls" section in your "app/config/security.yml", authentication is likely to fail and there's no hint displayed why it happened!

The Aimeos components have to be configured as well to get authentication working correctly. You need to take care of two things: Using the correct customer manager implementation and password encryption method. Both have to be added at the end of your ./app/config/config.yml as well:

  1. aimeos_shop:
  2.     mshop:
  3.         customer:
  4.             manager:
  5.                 name: FosUser
  6.                 password:
  7.                     name: Bcrypt

Setting the customer manager name to "FosUser" ensures that you can create and edit users stored in the "fos_user" table as well as referring to them in the shop components. The password encryption method is very important and watch out for the upper-case "B" in "Bcrypt". It needs to be the same as configured in the "app/config/security.yml" file (lower-case there)! Otherwise, authentication of every user will fail due to a password hash mismatch.

We highly recommend to use the Bcrypt hashing for passwords. This is the most secure method currently provided by the PHP interpreter. Unfortunately, it's built-in not before PHP 5.5 and if you use a previous version, you have to install the ircmaxell/password-compat via composer which also impments the necessary functions.

Add FOS user bundle routes

Adding the necessary routes for registration, login and the other features requires importing a view files from the bundle. Append these two lines at the end of your app/config/routing.yml file:

  1. fos_user:
  2.     resource: "@FOSUserBundle/Resources/config/routing/all.xml"

Restrict access

Setting up the security configuration is the most complex part. You have to use the lines below to your app/config/security.yml. If you already have a security configuration in that file, add each subsection below the security: -> providers | encoders | firewalls | access_control keys to the corresponding section in your security.yml file.

  1. security:
  2.     providers:
  3.         aimeos:
  4.             entity: { class: AimeosShopBundle:FosUser, property: username }
  5.  
  6.     encoders:
  7.         Aimeos\ShopBundle\Entity\FosUser: bcrypt
  8.  
  9.     firewalls:
  10.         aimeos_admin:
  11.             pattern:   ^/admin
  12.             anonymous: ~
  13.             provider: aimeos
  14.             form_login:
  15.                 login_path: /admin
  16.                 check_path: /admin_check
  17.         aimeos_myaccount:
  18.             pattern: ^/
  19.             form_login:
  20.                 provider: aimeos
  21.                 csrf_token_generator: security.csrf.token_manager
  22.             logout:       true
  23.             anonymous:    true
  24.  
  25.     access_control:
  26.         - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
  27.         - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
  28.         - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
  29.         - { path: ^/myaccount, roles: ROLE_USER }
  30.         - { path: ^/admin/.+, roles: ROLE_ADMIN }

The first section named providers ensures that the "FosUser" class of the Aimeos web shop bundle is used by the security framework if the provider "aimeos_customer" is referenced in one of the firewalls:

  1.     providers:
  2.         aimeos:
  3.             entity: { class: AimeosShopBundle:FosUser, property: username }

How to hash the password is configured in the encodes section. It basically says that Aimeos "FosUser" class hashes its passwords via the "bcrypt" algorithm. Remember the configuration in the "app/config/config.yml" file? There we've used "Bcrypt", now it must be lower-cased (bcrypt):

  1.     encoders:
  2.         Aimeos\ShopBundle\Entity\FosUser: bcrypt

In the firewalls section, the most errors occur so you should handle it with special care! The first one is for protecting the administration interface. It must be placed before the aimeos_myaccount firewall configuration:

  1.         aimeos_admin:
  2.             pattern:   ^/admin
  3.             anonymous: ~
  4.             provider: aimeos
  5.             form_login:
  6.                 login_path: /admin
  7.                 check_path: /admin_check

For the aimeos_myaccount section, the key is the one that's also used in the app/config/config.yml file for the fos_user.firewall_name setting. By default, the "pattern: ^/" line tells the Symfony security framework to watch at each request. This is necessary for protecting some URLs defined in the "access_control" section. The provider line refers to the configuration key in the first section ("providers") and must use the same name.

  1.         aimeos_myaccount:
  2.             pattern: ^/
  3.             form_login:
  4.                 provider: aimeos
  5.                 csrf_token_generator: security.csrf.token_manager
  6.             logout:       true
  7.             anonymous:    true

Keep care if your firewalls block contains several sections, espcecially if they use the same "pattern: ^/" line! Then, the first one is chosen and later won't be used, so your setup probably will not work.

Last but not least, the access_control section enforces users to be authorized. The first three lines are required by the FOS user bundle, the forth line protects the personal shop accounts of each user:

  1.     access_control:
  2.         - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
  3.         - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
  4.         - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
  5.         - { path: ^/myaccount, roles: ROLE_USER }
  6.         - { path: ^/admin/.+, roles: ROLE_ADMIN }

If you have a shop setup with several sites, the personal accounts of the users are located under the site code when it's configured like described there. Thus, you need a modified access control line in this case:

        - { path: ^/[^/]+/myaccount, roles: ROLE_USER }

Create admin accounts

You can create admin accounts from the command line using the aimeos:account command. There are two commands you have to execute:

./bin/console aimeos:account --admin <email address> [<site>]
./bin/console fos:user:promote <email address> ROLE_ADMIN

The first one creates the account in the fos_user table and adds the "admin" group to that account. Using the parameter --editor instead of "--admin", you can create limited accounts for the daily work of editors. The last parameter (<site>) is optional. It's value is used to create the account for the specific site. By default, the site "default" is used.

The second command adds the role "ROLE_ADMIN" to the account and the user will be granted by the firewall to access the /admin/ area.