MySQL authentication in Silex, the PHP micro-framework

Official documentation of Silex provides a lot of very useful examples to start a project. However, there is no complete example of setting up MySQL authentication. Here are the needed steps to accomplish that.


For our example, we will secure the entire application, this means that to access any URL, user will need the role ROLE_USER, which corresponds to an authenticated user.


1. DoctrineServiceProvider

$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
    'db.options' => array(
        'driver' => 'pdo_mysql',
        'dbhost' => 'localhost',
        'dbname' => 'mydbname',
        'user' => 'root',
        'password' => '',

2. SessionServiceProvider

$app->register(new Silex\Provider\SessionServiceProvider());

3. Namespace App

We will also need a specific class for authentication, here is how to declare a namespace called App. You can rename it as you wish.

Modify file composer.json:

"autoload": {
    "psr-0": {
        "App": "app/src/" // path to specific classes of our application

Register SecurityServiceProvider

This provider needs to update dependencies in composer.json file. Add the following:

"require": {
    "symfony/security": "2.1.*"

Registering provider:

$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'foo' => array('pattern' => '^/foo'), // Example of an url available as anonymous user
        'default' => array(
            'pattern' => '^.*$',
            'anonymous' => true, // Needed as the login path is under the secured area
            'form' => array('login_path' => '/', 'check_path' => 'login_check'),
            'logout' => array('logout_path' => '/logout'), // url to call for logging out
            'users' => $app->share(function() use ($app) {
                // Specific class App\User\UserProvider is described below
                return new App\User\UserProvider($app['db']);
    'security.access_rules' => array(
        // You can rename ROLE_USER as you wish
        array('^/.+$', 'ROLE_USER'),
        array('^/foo$', ''), // This url is available as anonymous user

App\User\UserProvider class

// app/src/App/User/UserProvider.php
namespace App\User;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\DBAL\Connection;
class UserProvider implements UserProviderInterface
    private $conn;
    public function __construct(Connection $conn)
        $this->conn = $conn;
    public function loadUserByUsername($username)
        $stmt = $this->conn->executeQuery('SELECT * FROM users WHERE username = ?', array(strtolower($username)));
        if (!$user = $stmt->fetch()) {
            throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
        return new User($user['username'], $user['password'], explode(',', $user['roles']), true, true, true, true);
    public function refreshUser(UserInterface $user)
        if (!$user instanceof User) {
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
        return $this->loadUserByUsername($user->getUsername());
    public function supportsClass($class)
        return $class === 'Symfony\Component\Security\Core\User\User';

Structure of table `users`

CREATE TABLE `users` (
  `username` VARCHAR(100) NOT NULL DEFAULT '',
  `password` VARCHAR(255) NOT NULL DEFAULT '',
  `roles` VARCHAR(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_username` (`username`)

User creation for test

-- Password is: password
INSERT INTO `users` (`username`, `password`, `roles`) VALUES ('johann', 'BFEQkknI/c+Nd7BaG7AaiyTfUFby/pkMHy3UsYqKqDcmvHoPRX/ame9TnVuOV2GrBH0JK9g4koW+CgTYI9mK+w==', 'ROLE_USER');

The password has been generated with code below:

echo $app['security.encoder.digest']->encodePassword('password', '');
// BFEQkknI/c+Nd7BaG7AaiyTfUFby/pkMHy3UsYqKqDcmvHoPRX/ame9TnVuOV2GrBH0JK9g4koW+CgTYI9mK+w==

Example of use with Twig

Add dependency in composer.json file:

"require": {
    "symfony/twig-bridge": "2.1.*"
use Symfony\Component\HttpFoundation\Request;
$app->register(new Silex\Provider\TwigServiceProvider(), array(
    'twig.path' => __DIR__ . '/views',
$app->get('/', function(Request $request) use ($app) {
    return $app['twig']->render('index.twig', array(
        'error' => $app['security.last_error']($request),
        'last_username' => $app['session']->get('_security.last_username'),
{% if is_granted('ROLE_USER') %}
    <p>Welcome {{ }}!</p>
    <p><a href="{{ path('logout') }}">Log out</a></p>
{% else %}
    <form action="{{ path('login_check') }}" method="post">
        <p><label for="username">Username: </label><input id="username" type="text" name="_username" value="{{ last_username }}"></p>
        <p><label for="password">Password: </label><input id="password" type="password" name="_password"></p>
        <p><input type="submit" value="Log in"></p>
        {% if error %}
            <div class="error">{{ error }}</div>
        {% endif %}
{% endif %}


This is a simple example that could be improved by using an ORM and our own User class, maybe in another article :)

21 Responses to “MySQL authentication in Silex, the PHP micro-framework”

  1. Maksim says:

    Great article. But are you sure about dependencies ? I have
    ReflectionException: Class Request does not exist
    And I have no I idea which class php can’t find.

    • Johann Reinke says:

      Request class comes from Symfony\Component\HttpFoundation\Request
      You should add this line in top of your file :
      use Symfony\Component\HttpFoundation\Request;

  2. Maksim says:

    Thanks, It helps. But now I have error with Twig it can’t recognize is_granted(). Is this additional extention?

  3. Maksim says:

    ‘Identifier “security.authentication_providers” is not defined. Very wired … I’m already have ‘users’ => $app->share(function() use ($app)
    // Specific class App\User\UserProvider is described below
    return new App\User\UserProvider($app['db']);

  4. GromNaN says:

    Great article. Having it in the cookbook for Silex documentation would make it accessible to everybody.

  5. Antonio says:

    Nice article. However, I keep getting an annoying error saying:

    Twig_Error_Syntax: The function “path” does not exist in “index.twig” at line 3

    Any idea? I have looked around the web but no one seems to have had the same problem.

  6. Gerrit says:

    Thanks for the great article !

  7. Marcin Kłeczek says:

    Thank you, very good article. Good start to “full feature” authentication.

  8. René de Kat says:


    Thanks for writing this tutorial. I am very new to Silex/Symfony and coming from Zend Framework I am in sort of a transition phase.

    I tried to integrate this into a simple project, but I keep getting: Bad credentials.

    Would anyone have a look at the example code here:

    I’ve commented all MySQL code, and hardcoded some username and password in. MySQL will be replaced with Mongo in my project.

    Thanks in advance for anyone who can shed some light on this.

    • René de Kat says:

      Problem solved. Everything works like a charm now.

      The problem was I tested without encrypted passwords first and after that an encrypted version of an empty string which is no good.

      All works perfectly now with an encrypted string > 0 chars.

      • Dwi says:


        I have the same issue with error ‘Bad credentials’, I also debug the user object in the App\User\UserProvider.php is correctly fetched from the database. I understand that this is not the only part of user authentication, and it looks like that error message came from:


        Where should I go to debug the underlying problem?


  9. Stephan says:

    I’m getting a fatal error:

    Fatal error: Class ‘Doctrine\DBAL\Configuration’ not found in (..) vendor/silex/silex/src/Silex/Provider/DoctrineServiceProvider.php

    How can I fix this?

  10. Jean Christophe says:

    Juste une question … Faut il écrire la fonction qui correspond à la route du check_path ?
    Quelque chose du genre
    Par avance meri

    • Pingax says:

      Non, check_path est définie automatiquement par Silex.

      Extrait de la doc : “The admin_login_check route is automatically defined by Silex and its name is derived from the check_path value (all / are replaced with _ and the leading / is stripped).”

      Très bon article, que je bookmark de ce pas !

  11. James says:

    Thanks for the article! This utilises PHP for the config – I’m using YAML. Is there any way to link the users to the right class using YAML instead of PHP?

  12. switcherdav says:

    Alors là un grand merci pour ton article.

    newbie sur ce framework, j’avais juste oublié d’ajouter /index.php dans mon URL pour que ça fonctionne (vu que je ne me suis pas encore occupé du htaccess)

    Reste maintenant à décortiquer le code pour être capable de le reproduire …

  13. DK says:

    Very simplified version…
    One question-
    I am new to silex…What are the considerations if we want to just use Rest api based authentication tokens for server and client side…

Leave a Reply

* Required fields