Security

Authentication and Firewalls (i.e. Getting the User's Credentials)

You can configure Symfony to authenticate your users using any method you want and to load user information from any source. This is a complex topic, but the Security guide has a lot of information about this.

Regardless of your needs, authentication is configured in security.yaml, primarily under the firewalls key.

Best Practice

Unless you have two legitimately different authentication systems and users (e.g. form login for the main site and a token system for your API only), we recommend having only one firewall entry with the anonymous key enabled.

Most applications only have one authentication system and one set of users. For this reason, you only need one firewall entry. If you have separated web and API sections on your site, you will need more firewall entries. But the point is to keep things simple.

Additionally, you should use the anonymous key under your firewall. If you need to require users to be logged in for different sections of your site (or maybe nearly all sections), use the access_control area.

Best Practice

Use the bcrypt encoder for hashing your users' passwords.

If your users have a password, then we recommend hashing it using the bcrypt encoder, instead of the traditional SHA-512 hashing encoder. The main advantages of bcrypt are the inclusion of a salt value to protect against rainbow table attacks, and its adaptive nature, which allows to make it slower to remain resistant to brute-force search attacks.

Note

Sodium is the hashing algorithm as recommended by industry standards, but this won't be available to you unless you are using PHP 7.2+ or have the libsodium extension installed. bcrypt is sufficient for most applications.

With this in mind, here is the authentication setup from our application, which uses a login form to load users from the database:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# config/packages/security.yaml
security:
    encoders:
        App\Entity\User: bcrypt

    providers:
        database_users:
            entity: { class: App\Entity\User, property: username }

    firewalls:
        secured_area:
            pattern: ^/
            anonymous: true
            form_login:
                check_path: login
                login_path: login

            logout:
                path: security_logout
                target: homepage

# ... access_control exists, but is not shown here

Tip

The source code for our project contains comments that explain each part.