Need help with Drupal or Grav admin, site building, design, or content? Contact us! 

Help Defend Democracy! → Join Battalion today.

Back to top with progress scrollbar

Examine the Reassuringly Robust Flexibility and Extensibility of Symfony Security

By Reuben Walker, 9 October, 2023
Circuit board with hacker in hoodie superimposed

It’s long past time to make your Symfony applications as secure as possible.

As should be obvious to anyone not living under a rock, cybersecurity is critical. This has always been the case, but it’s even more important now thanks to the Russian war crimes in Ukraine.

The potential for a cyber-war has never been higher. As Russia struggles with illegally occupying Ukraine it may lash out with cyber-attacks against anyone supporting the Ukrainian nation.

Russia’s fellow rogue state allies, Belarus, Iran, North Korea, and China, could increase their current efforts. Plus, many cyber-criminal gangs are based in these countries.

In this article, we will examine Symfony’s security system. I am not a Symfony security professional so I will quote Symfony often and paraphrase it even more.

Non-Symfony Security

But before we look at Symfony, there are many things you should be doing for security, regardless of the platform you use.

Techniques you should implement include:

How to maximize your Symfony Application’s Security

First of all, after reading this overview, be sure to review the Symfony security docs and the SymfonyCasts security course. Bookmark these links, as everything will not be covered in detail in this article. However, we will provide documentation links to the relevant security techniques we explore here. 

SymfonyCasts is a paid service well worth the expense. Here’s their description of the course, “It's security time! Symfony 5.3 comes with a reimagined version of its security system and I ❤️it! Yes, it's still super flexible & dependable. But the "guts" have been streamlined and simplified, making it easier to get your job done and giving you readable code if you need to dive into the core.

In this course, we'll go from an introduction into Symfony security into a full-blown application with users, permissions, custom voters and multiple ways to authenticate.”

So, check it out.

Symfony notes that it “provides many tools to secure your application. Some HTTP-related security tools, like secure session cookies and CSRF protection, are provided by default. The SecurityBundle provides all the authentication and authorization features needed to secure your application.

A bundle is similar to a plugin in other software but even better. The core features of the Symfony framework are implemented with bundles (FrameworkBundle, SecurityBundle, DebugBundle, etc.)”

There are also third-party security bundles. Below we will look at a 2FA one.

Symfony Flex

For ease of use with the installation of third-party bundles in general, you should implement Symfony Flex.

Again, Symfony notes “A common practice when developing Symfony applications is to install packages (Symfony calls them bundles) that provide ready-to-use features. Packages usually require some setup before using them (editing some files to enable the bundle, creating some files to add some initial config, etc.)

This setup can be automated and that's why Symfony includes Symfony Flex, a tool to simplify the installation/removal of packages in Symfony applications. Technically speaking, Symfony Flex is a Composer plugin that is installed by default when creating a new Symfony application and which automates the most common tasks of Symfony applications.”

You can learn more about Flex in Chapters from SymfonyCasts' free Symfony 6: Harmonious Development Course:

What are we going to review?

Symfony security includes techniques like:

User Permissions

Symfony permissions are linked to a user object. If you need to secure (parts of) your application, you need to create a user class. It will implement UserInterface. While it’s often a Doctrine entity, you can also use a dedicated Security user class.

Symfony notes “Symfony comes with several built-in user providers:

The built-in user providers cover the most common needs for applications, but you can also create a custom user provider.”

Password Hashing

Most applications require their users to log in via a password. If this is the case for you, the Symfony SecurityBundle provides password hashing and verification functionality

You can access the details in the documentation.

SchebTwoFactorBundle

Symfony notes “the bundle hooks into the security layer and listens for authentication events. When a user login appears and the user has two-factor authentication enabled, access and privileges are temporarily withheld, putting the authentication status into an intermediate state. The user is challenged to enter a valid two-factor authentication code. Only when that code is entered correctly, the associated roles are granted.

To represent the state between login and a valid two-factor code being entered, the bundle introduces the role-like attribute IS_AUTHENTICATED_2FA_IN_PROGRESS, which can be used in is_granted() calls. IS_AUTHENTICATED_FULLY is – just like roles – withheld until the two-factor authentication step has been completed successfully.”

The bundle works out of the box with:

Firewall/Authentication

Again Symfony notes “The firewalls section of config/packages/security. YAML is the most important section. A "firewall" is your authentication system: the firewall defines which parts of your application are secured and how your users will be able to authenticate (e.g. login form, API token, etc).

Only one firewall is active on each request: Symfony uses the pattern key to find the first match (you can also match by the host or other things).

The dev firewall is a fake firewall: it makes sure that you don't accidentally block Symfony's dev tools - which live under URLs like /_profiler and /_wdt.

All real URLs are handled by the main firewall (no pattern key means it matches all URLs). A firewall can have many modes of authentication, in other words, it enables many ways to ask the question "Who are you?".”

The SecurityBundle comes with many authenticators:

Limiting Login Attempts

Symfony provides basic protection against brute force login attacks via enabling the login_throttling setting.

Authorization/Access Control

This security technique is fairly standard. Users log in to your app using your login form. You can deny access and work with the User object. That’s authorization, and it decides if a user can access some resource (a URL, a model object, a method call, etc).

The process has two sides:

  1. The user receives a specific role when logging in (e.g. ROLE_ADMIN).
  2. You add code so that a resource (e.g. URL, controller) requires a specific "attribute" (e.g. a role like ROLE_ADMIN) to be accessed.

Voters are Symfony's most powerful way of managing permissions. They allow you to centralize all permission logic, then reuse them in many places.

Security Events

Symfony notes “During the authentication process, multiple events are dispatched that allow you to hook into the process or customize the response sent back to the user. You can do this by creating an event listener or subscriber for these events.”Symfony Security events illustration

Authentication events include:

  • CheckPassportEvent - Dispatched after the authenticator created the security passport. Listeners of this event do the actual authentication checks (such as checking the passport, validating the CSRF token, etc.)
  • AuthenticationTokenCreatedEvent - Dispatched after the passport was validated and the authenticator created the security token (and user). This can be used in advanced use-cases where you need to modify the created token (e.g. for multi-factor authentication).
  • AuthenticationSuccessEvent - Dispatched when authentication is nearing success. This is the last event that can make an authentication fail by throwing an AuthenticationException.
  • LoginSuccessEvent - Dispatched after authentication was fully successful. Listeners to this the event can modify the response sent back to the user.
  • LoginFailureEvent - Dispatched after an AuthenticationException was thrown during authentication. Listeners to this event can modify the error response sent back to the user.

Other Events

How to Implement CSRF Protection

Symfony notes “CSRF - or Cross-site request forgery - is a method by which a malicious user attempts to make your legitimate users unknowingly submit data that they don't intend to submit.

CSRF protection works by adding a hidden field to your form that contains a value that only you and your user know. This ensures that the user - not some other entity - is submitting the given data.

Authenticating against an LDAP server

If you are using an LDAP server, Symfony provides several ways to work with it.

They note “the Security component offers:

  • The LDAP user provider uses the LdapUserProvider class. Like all other user providers, it can be used with any authentication provider.
  • The form_login_ldap authentication provider, for authenticating against an LDAP server using a login form. Like all other authentication providers, it can be used with any user provider.
  • The http_basic_ldap authentication provider, for authenticating against an LDAP server using HTTP Basic. Like all other authentication providers, it can be used with any user provider.

This means that the following scenarios will work:

  • Checking a user's password and fetching user information against an LDAP server. This can be done using both the LDAP user provider and either the LDAP form login or LDAP HTTP Basic authentication providers.
  • Checking a user's password against an LDAP server while fetching user information from another source (database using FOSUserBundle, for example).
  • Loading user information from an LDAP server, while using another authentication strategy (token-based pre-authentication, for example).”

Conclusion

We have now reviewed the basics of Symfony security.

You can see how (fortunately) it is very extensive and flexible. It allows you many options for how you want to implement its best practices. You can customize security based on your server, business logic, security events, authorization roles, authenticators, user providers, plus other practices not covered here.

As noted above explore the Symfony security documentation in detail. Also, consider subscribing to SymfonyCasts and taking the security course

To close please make sure your Symfony application is as secure as possible by implementing these best practices. It’s vital that you keep your users safe from cyber-criminals and the enemies of democracy. Security is just as important as speed, usability, accessibility, search optimization, and the other aspects of your app. 

It's our responsibility to ensure application security is providing maximum effectiveness.

Stay safe Symfonistas!

section separator
Article Type
Donate using Liberapay

Symfony Station covers the essential news in the Symfony, PHP, and Fediverse development communities with a focus on protecting democracy. Please use the button above to make a small donation to help cover our out-of-pocket costs. Our labor is provided free of charge to support the communities we write about.

Join our newsletter list

Subscribe to The Payload, our weekly newsletter exploring the Symfony Universe.

  Start exploring!