Search code examples
symfonysecurityauthenticationsilex

Silex: Security authentication system attempts to run 'login_check' route


I'm trying to configure the authentication system in Silex. However, the following error pops up: Error

Of course I've been searching for a solution on the internet. But every topic says the 'login_check' should be behind the firewall. Therefore, it is placed in the /Users/ area.

I've tried to get into the protected area. However, the firewall works, because I get redirected back to the login page. I'm using the following lines of code to get what I want.

The registering part:

$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'login_path' => array(
            'pattern' => '^/Security/login$',
            'anonymous' => true
        ),
        'default' => array(
            'pattern' => '^/Security/User/.*$',
            'anonymous' => true,
            'form' => array(
                'login_path' => '/Security/login',
                'check_path' => '/Security/User/login_check',
            ),
            'logout' => array(
                'logout_path' => '/Security/User/logout',
                'invalidate_session' => false
            ),
            'users' => function($app) { 
                return new User\UserProvider($app['db']); 
            },
        )
    ),
    'security.access_rules' => array(
        array('^/Security/login$', 'IS_AUTHENTICATED_ANONYMOUSLY'),
        array('^/Security/User/.+$', 'ROLE_USER')
    )
));

The login route:

$routes->match('/login', function(Request $request) use ($app) {
    return $app['twig']->render('form.html.twig', array(
        'error' => $app['security.last_error']($request),
        'last_username' => $app['session']->get('_security.last_username'),
    ));
})->bind('login');

$routes->match('/User/page', function () use ($app) {
    return $app['twig']->render('index.html.twig', array());
})->bind('user.page');

Form.html.twig:

{% extends "layout.html.twig" %}

{% block content %}
    {% if is_granted('ROLE_USER') %}
        <p>Welcome {{ app.security.token.user.username }}!</p>
        <p><a href="{{ path('/User/logout') }}">Log out</a></p>
    {% else %}
        <form action="{{ path('/User/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 %}
        </form>
    {% endif %}
{% endblock %}

Who can tell me why the system still tries to execute the login_check route? It should be handled by Silex. And it is located in the protected area.


Solution

  • Function path accepts route name as parameter, not url. Security provider makes fake routes for paths check_path and logout_path. Their names depend on the paths, route name is path where all occurrences of / are replaced with _.

    So for you case check_path route name is Security_User_login_check and logout_path route name is Security_User_logout.

    Fix path calls to {{ path('Security_User_login_check') }} and {{ path('Security_User_logout') }}