Now that we have a running application, we need to add a database (because… databases). For this tutorial, we will use the database to add authentication to our application using Symfony’s MakerBundle.

Not for Production

This series is about getting Symfony working on Dokku - not creating production ready code. Use what we build here as a base for building your own applications, but do not use this code as-is.

Database Migrations

Adding Migration 0

This is completely optional, but it is something I do. Though Doctrine’s migrations do support a migrate first command, they do not support a “rebuild” or similar command. This means the down method on your first migration can never be run. The only option you have is to drop and re-create the entire database if you want to rebuild your database from scratch (which you may want to frequently for development or testing).

Create a new migration file src/Migrations/Version20010101000000.php with the content:

Scaffolding Authentication

Symfony makes it fairly easy with the MakerBundle to add a basic User entity and authentication. We can then build out the generated code into what meets our needs.

The User Entity

First we need to create a User entity, which we will do following the instructions in the Symfony documentation.

Password Hashing: bcrypt vs. Argon2

If you are asked if you want to use Argon2i for password hashing, select no.

I have had problems with getting Argon2 password hashing working with the Dokku PHP image. Because of this, we are going to use bcrypt in our configuration.

Run the make:user generator and use the following answers:

sf make:user
The name of the security user class (e.g. User) [User]:
> User
Do you want to store user data in the database (via Doctrine)? (yes/no) [yes]:
> yes
Enter a property name that will be the unique "display" name for the user (e.g.
email, username, uuid [email]
> email
Does this app need to hash/check user passwords? (yes/no) [yes]:
> yes
The newer Argon2i password hasher requires PHP 7.2, libsodium or paragonie/sodium_compat. Your system DOES support this algorithm.
You should use Argon2i unless your production system will not support it.
Use Argon2i as your password hasher (bcrypt will be used otherwise)? (yes/no) [yes]:
> no

The Authentication System

sf make:auth
What style of authentication do you want? [Empty authenticator]:
[0] Empty authenticator
[1] Login form authenticator
> 1
The class name of the authenticator to create (e.g. AppCustomAuthenticator):
> LoginFormAuthenticator
Choose a name for the controller class (e.g. SecurityController) [SecurityController]:
> SecurityController

After the generator creates the authentication files, we need to update the App\Security\LoginFormAuthenticator::onAuthenticationSuccess() method (in src/Security/LoginFormAuthenticator.php, around line 89).

Migrating a User Table

Though there is a make:migration command, we will not use it. The migration it creates is filled with database platform-specific code. If we ever want to change database server (MariaDB to PostgreSQL) or even use SQLite for running PHPUnit tests, the migrations would fail. Instead, we will create a migration that be run independent of platform.

Instead, we will use the DoctrineMigrationBundle’s doctrine:migrations:generate command to create an empty migration and then update it with our migration code. First, generate the migration:

sf doctrine:migrations:generate

And the content for the generated migration:

Correct Class Name

The migration I generated was src/Migrations/Version20190203003048.php and so the class name is Version20190203003048.

When using the code below, make sure to the class name generated for your migration. If you just copy and paste, you will get an error.

Add User Command

Building out an entire user registration system will be the focus of a later post in this series. Instead, we will add a console command to add users manually. This will also be useful for adding our first admin user to the system. The MakerBundle has a generator for console commands and we will use it with the following answers:

sf make:command
Choose a command name:
> app:add-user

Open the new src/Command/AddUserCommand.php file and replace the boilerplate with the following:

You can now visit http://localhost:8000/login (you will need to start the server with sf server:run if you had stopped it previously) and enter the username and password to log in your test admin user. You should see the test admin’s information in the debug bar at the bottom of the page.

Logging Out

Now that we can log in, we need a way to log out. First we need a route to our config/routes.yaml file:

logout:path:/logout

Log Out Method

Instead of adding a route to our config/routes.yaml file, we could instead add a method to our src/Controller/SecurityController.php:

This will take a while to run, but when its done, we can add a new user.

Adding User to the Live Site

To add a user, we are going to run our app:add-user command. This time, use your email and a secure password. The dokku enter command will log us into the application container on the server. Once in we can run the app:add-user command (we do have to php bin/console because we do not have our alias) and then exit the server.