Thursday, August 16, 2018

How to Do User Authentication With the Symfony Security Component

How to Do User Authentication With the Symfony Security Component

In this article, you'll learn how to set up user authentication in PHP using the Symfony Security component. As well as authentication, I'll show you how to use its role-based authorization, which you can extend according to your needs.

The Symfony Security Component

The Symfony Security Component allows you to set up security features like authentication, role-based authorization, CSRF tokens and more very easily. In fact, it's further divided into four sub-components which you can choose from according to your needs.

The Security component has the following sub-components:

  • symfony/security-core
  • symfony/security-http
  • symfony/security-csrf
  • symfony/security-acl

In this article, we are going to explore the authentication feature provided by the symfony/security-core component.

As usual, we'll start with the installation and configuration instructions, and then we'll explore a few real-world examples to demonstrate the key concepts.

Installation and Configuration

In this section, we are going to install the Symfony Security component. I assume that you have already installed Composer on your system—we'll need it to install the Security component available at Packagist.

So go ahead and install the Security component using the following command.

We are going to load users from the MySQL database in our example, so we'll also need a database abstraction layer. Let's install one of the most popular database abstraction layers: Doctrine DBAL.

That should have created the composer.json file, which should look like this:

Let's modify the composer.json file to look like the following one.

As we have added a new classmap entry, let's go ahead and update the composer autoloader by running the following command.

Now, you can use the Sfauth namespace to autoload classes under the src directory.

So that's the installation part, but how are you supposed to use it? In fact, it's just a matter of including the autoload.php file created by Composer in your application, as shown in the following snippet.

A Real-World Example

Firstly, let's go through the usual authentication flow provided by the Symfony Security component.

  • The first thing is to retrieve the user credentials and create an unauthenticated token.
  • Next, we'll pass an unauthenticated token to the authentication manager for validation.
  • The authentication manager may contain different authentication providers, and one of them will be used to authenticate the current user request. The logic of how the user is authenticated is defined in the authentication provider.
  • The authentication provider contacts the user provider to retrieve the user. It's the responsibility of the user provider to load users from the respective back-end.
  • The user provider tries to load the user using the credentials provided by the authentication provider. In most cases, the user provider returns the user object that implements the UserInterface interface.
  • If the user is found, the authentication provider returns an unauthenticated token, and you can store this token for the subsequent requests.

In our example, we are going to match the user credentials against the MySQL database, thus we'll need to create the database user provider. We'll also create the database authentication provider that handles the authentication logic. And finally, we'll create the User class, which implements the UserInterface interface.

The User Class

In this section, we'll create the User class which represents the user entity in the authentication process.

Go ahead and create the src/User/User.php file with the following contents.

The important thing is that the User class must implement the Symfony Security UserInterface interface. Apart from that, there's nothing out of the ordinary here.

The Database Provider Class

It's the responsibility of the user provider to load users from the back-end. In this section, we'll create the database user provider, which loads the user from the MySQL database.

Let's create the src/User/DatabaseUserProvider.php file with the following contents.

The user provider must implement the UserProviderInterface interface. We are using the doctrine DBAL to perform the database-related operations. As we have implemented the UserProviderInterface interface, we must implement the loadUserByUsername, refreshUser, and supportsClass methods.

The loadUserByUsername method should load the user by the username, and that's done in the getUser method. If the user is found, we return the corresponding Sfauth\User\User object, which implements the UserInterface interface.

On the other hand, the refreshUser method refreshes the supplied User object by fetching the latest information from the database.

And finally, the supportsClass method checks if the DatabaseUserProvider provider supports the supplied user class.

The Database Authentication Provider Class

Finally, we need to implement the user authentication provider, which defines the authentication logic—how a user is authenticated. In our case, we need to match the user credentials against the MySQL database, and thus we need to define the authentication logic accordingly.

Go ahead and create the src/User/DatabaseAuthenticationProvider.php file with the following contents.

The DatabaseAuthenticationProvider authentication provider extends the UserAuthenticationProvider abstract class. Hence, we need to implement the retrieveUser and checkAuthentication abstract methods.

The job of the retrieveUser method is to load the user from the corresponding user provider. In our case, it will use the DatabaseUserProvider user provider to load the user from the MySQL database.

On the other hand, the checkAuthentication method performs the necessary checks in order to authenticate the current user. Please note that I've used the MD5 method for password encryption. Of course, you should use more secure encryption methods to store user passwords.

How It Works Altogether

So far, we have created all the necessary elements for authentication. In this section, we'll see how to put it all together to set up the authentication functionality.

Go ahead and create the db_auth.php file and populate it with the following contents.

Recall the authentication flow which was discussed in the beginning of this article—the above code reflects that sequence.

The first thing was to retrieve the user credentials and create an unauthenticated token.

Next, we have passed that token to the authentication manager for validation.

When the authenticate method is called, a lot of things are happening behind the scenes.

Firstly, the authentication manager selects an appropriate authentication provider. In our case, it's the DatabaseAuthenticationProvider authentication provider, which will be selected for authentication.

Next, it retrieves the user by the username from the DatabaseUserProvider user provider. Finally, the checkAuthentication method performs the necessary checks to authenticate the current user request.

Should you wish to test the db_auth.php script, you'll need to create the sf_users table in your MySQL database.

Go ahead and run the db_auth.php script to see how it goes. Upon successful completion, you should receive an authenticated token, as shown in the following snippet.

Once the user is authenticated, you can store the authenticated token in the session for the subsequent requests.

And with that, we've completed our simple authentication demo!

Conclusion

Today, we looked at the Symfony Security component, which allows you to integrate security features in your PHP applications. Specifically, we discussed the authentication feature provided by the symfony/security-core sub-component, and I showed you an example of how this functionality can be implemented in your own app.

Feel free to post your thoughts using the feed below!


No comments:

Post a Comment