The Entry Point: Helping Users Start Authentication

5.3 version
Symfony 5.3 is backed by JoliCode.

The Entry Point: Helping Users Start Authentication

When an unauthenticated user tries to access a protected page, Symfony gives them a suitable response to let them start authentication (e.g. redirect to a login form or show a 401 Unauthorized HTTP response for APIs).

However sometimes, one firewall has multiple ways to authenticate (e.g. both a form login and a social login). In these cases, it is required to configure the authentication entry point.

You can configure this using the entry_point setting:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    # config/packages/security.yaml
    security:
        enable_authenticator_manager: true
    
        # ...
        firewalls:
            main:
                # allow authentication using a form or a custom authenticator
                form_login: ~
                custom_authenticators:
                    - App\Security\SocialConnectAuthenticator
    
                # configure the form authentication as the entry point for unauthenticated users
                entry_point: form_login
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <!-- config/packages/security.xml -->
    <?xml version="1.0" encoding="UTF-8"?>
    <srv:container xmlns="http://symfony.com/schema/dic/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:srv="http://symfony.com/schema/dic/services"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/security
            https://symfony.com/schema/dic/security/security-1.0.xsd">
    
        <config enable-authenticator-manager="true">
            <!-- ... -->
    
            <!-- entry-point: configure the form authentication as the entry
                              point for unauthenticated users -->
            <firewall name="main"
                entry-point="form_login"
            >
                <!-- allow authentication using a form or a custom authenticator -->
                <form-login/>
                <custom-authenticator>App\Security\SocialConnectAuthenticator</custom-authenticator>
            </firewall>
        </config>
    </srv:container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // config/packages/security.php
    use Symfony\Config\SecurityConfig;
    use App\Security\SocialConnectAuthenticator;
    
    return static function (SecurityConfig $security) {
        $security->enableAuthenticatorManager(true);
        // ....
    
    
        // allow authentication using a form or HTTP basic
        $mainFirewall = $security->firewall('main');
        $mainFirewall
            ->formLogin()
            ->customAuthenticators([SocialConnectAuthenticator::class])
    
            // configure the form authentication as the entry point for unauthenticated users
            ->entryPoint('form_login');
        ;
    };
    

Note

You can also create your own authentication entry point by creating a class that implements Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface. You can then set entry_point to the service id (e.g. entry_point: App\Security\CustomEntryPoint)

Multiple Authenticators with Separate Entry Points

However, there are use cases where you have authenticators that protect different parts of your application. For example, you have a login form that protects the main website and API end-points used by external parties protected by API keys.

As you can only configure one entry point per firewall, the solution is to split the configuration into two separate firewalls:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    # config/packages/security.yaml
    security:
        # ...
        firewalls:
            api:
                pattern: ^/api/
                custom_authenticators:
                    - App\Security\ApiTokenAuthenticator
            main:
                lazy: true
                form_login: ~
    
        access_control:
            - { path: '^/login', roles: PUBLIC_ACCESS }
            - { path: '^/api', roles: ROLE_API_USER }
            - { path: '^/', roles: ROLE_USER }
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <!-- config/packages/security.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <srv:container xmlns="http://symfony.com/schema/dic/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:srv="http://symfony.com/schema/dic/services"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/security
            https://symfony.com/schema/dic/security/security-1.0.xsd">
    
        <config>
            <!-- ... -->
            <firewall name="api" pattern="^/api/">
                <custom-authenticator>App\Security\ApiTokenAuthenticator</custom-authenticator>
            </firewall>
    
            <firewall name="main" anonymous="true" lazy="true">
                <form-login/>
            </firewall>
    
            <rule path="^/login" role="PUBLIC_ACCESS"/>
            <rule path="^/api" role="ROLE_API_USER"/>
            <rule path="^/" role="ROLE_USER"/>
        </config>
    </srv:container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // config/packages/security.php
    use App\Security\ApiTokenAuthenticator;
    use App\Security\LoginFormAuthenticator;
    use Symfony\Config\SecurityConfig;
    
    return static function (SecurityConfig $security) {
        $apiFirewall = $security->firewall('api');
        $apiFirewall
            ->pattern('^/api')
            ->customAuthenticators([ApiTokenAuthenticator::class])
        ;
    
        $mainFirewall = $security->firewall('main');
        $mainFirewall
            ->lazy(true)
            ->formLogin();
    
        $accessControl = $security->accessControl();
        $accessControl->path('^/login')->roles(['IS_AUTHENTICATED_ANONYMOUSLY']);
        $accessControl->path('^/api')->roles(['ROLE_API_USER']);
        $accessControl->path('^/')->roles(['ROLE_USER']);
    };
    

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.