Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • SensioLabs Professional services to help you with Symfony
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by SensioLabs
  1. Home
  2. Documentation
  3. Security
  4. Authenticating against an LDAP server
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud

Table of Contents

  • Installation
  • Ldap Configuration Reference
  • Configuring the LDAP client
  • Fetching Users Using the LDAP User Provider
    • service
    • base_dn
    • search_dn
    • search_password
    • default_roles
    • uid_key
    • extra_fields
    • filter
  • Authenticating against an LDAP server
    • service
    • dn_string
    • query_string
    • Configuration example for form login
    • Configuration example for HTTP Basic
    • Configuration example for form login and query_string

Authenticating against an LDAP server

Edit this page

Authenticating against an LDAP server

Symfony provides different means to work with an LDAP server.

The Security component offers:

  • The ldap user provider, using the LdapUserProvider class. Like all other user providers, it can be used with any authentication provider.
  • The form_login_ldap authentication provider, for authenticating against an LDAP server using a login form. Like all other authentication providers, it can be used with any user provider.
  • The http_basic_ldap authentication provider, for authenticating against an LDAP server using HTTP Basic. Like all other authentication providers, it can be used with any user provider.

This means that the following scenarios will work:

  • Checking a user's password and fetching user information against an LDAP server. This can be done using both the LDAP user provider and either the LDAP form login or LDAP HTTP Basic authentication providers.
  • Checking a user's password against an LDAP server while fetching user information from another source (database using FOSUserBundle, for example).
  • Loading user information from an LDAP server, while using another authentication strategy (token-based pre-authentication, for example).

Installation

In applications using Symfony Flex, run this command to install the Ldap component before using it:

1
$ composer require symfony/ldap

Ldap Configuration Reference

See Security Configuration Reference (SecurityBundle) for the full LDAP configuration reference (form_login_ldap, http_basic_ldap, ldap). Some of the more interesting options are explained below.

Configuring the LDAP client

All mechanisms actually need an LDAP client previously configured. The providers are configured to use a default service named ldap, but you can override this setting in the security component's configuration.

An LDAP client can be configured using the built-in LDAP PHP extension with the following service definition:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# config/services.yaml
services:
    Symfony\Component\Ldap\Ldap:
        arguments: ['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
        tags:
            - ldap
    Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
        arguments:
            -   host: my-server
                port: 389
                encryption: tls
                options:
                    protocol_version: 3
                    referrals: false
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/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
        <service id="Symfony\Component\Ldap\Ldap">
            <argument type="service" id="Symfony\Component\Ldap\Adapter\ExtLdap\Adapter"/>
            <tag name="ldap"/>
        </service>
        <service id="Symfony\Component\Ldap\Adapter\ExtLdap\Adapter">
            <argument type="collection">
                <argument key="host">my-server</argument>
                <argument key="port">389</argument>
                <argument key="encryption">tls</argument>
                <argument key="options" type="collection">
                    <argument key="protocol_version">3</argument>
                    <argument key="referrals">false</argument>
                </argument>
            </argument>
        </service>
    </services>
</container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// config/services.php
use Symfony\Component\Ldap\Adapter\ExtLdap\Adapter;
use Symfony\Component\Ldap\Ldap;

$container->register(Ldap::class)
    ->addArgument(new Reference(Adapter::class))
    ->tag('ldap');

$container
    ->register(Adapter::class)
    ->setArguments([
        'host' => 'my-server',
        'port' => 389,
        'encryption' => 'tls',
        'options' => [
            'protocol_version' => 3,
            'referrals' => false
        ],
    ]);

Fetching Users Using the LDAP User Provider

If you want to fetch user information from an LDAP server, you may want to use the ldap user provider.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# config/packages/security.yaml
security:
    # ...

    providers:
        my_ldap:
            ldap:
                service: Symfony\Component\Ldap\Ldap
                base_dn: dc=example,dc=com
                search_dn: "cn=read-only-admin,dc=example,dc=com"
                search_password: password
                default_roles: ROLE_USER
                uid_key: uid
                extra_fields: ['email']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 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>
        <provider name="my_ldap">
            <ldap service="Symfony\Component\Ldap\Ldap"
                base-dn="dc=example,dc=com"
                search-dn="cn=read-only-admin,dc=example,dc=com"
                search-password="password"
                default-roles="ROLE_USER"
                uid-key="uid"/>
        </provider>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// config/packages/security.php
use Symfony\Component\Ldap\Ldap;
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->provider('ldap_users')
        ->ldap()
            ->service(Ldap::class)
            ->baseDn('dc=example,dc=com')
            ->searchDn('cn=read-only-admin,dc=example,dc=com')
            ->searchPassword('password')
            ->defaultRoles(['ROLE_USER'])
            ->uidKey('uid')
            ->extraFields(['email'])
    ;
};

Caution

The Security component escapes provided input data when the LDAP user provider is used. However, the LDAP component itself does not provide any escaping yet. Thus, it's your responsibility to prevent LDAP injection attacks when using the component directly.

Caution

The user configured above in the user provider is only used to retrieve data. It's a static user defined by its username and password (for improved security, define the password as an environment variable).

If your LDAP server allows retrieval of information anonymously, you can set the search_dn and search_password options to null.

The ldap user provider supports many different configuration options:

service

type: string default: ldap

This is the name of your configured LDAP client. You can freely choose the name, but it must be unique in your application and it cannot start with a number or contain white spaces.

base_dn

type: string default: null

This is the base DN for the directory

search_dn

type: string default: null

This is your read-only user's DN, which will be used to authenticate against the LDAP server to fetch the user's information.

search_password

type: string default: null

This is your read-only user's password, which will be used to authenticate against the LDAP server to fetch the user's information.

default_roles

type: array default: []

This is the default role you wish to give to a user fetched from the LDAP server. If you do not configure this key, your users won't have any roles, and will not be considered as authenticated fully.

uid_key

type: string default: null

This is the entry's key to use as its UID. Depends on your LDAP server implementation. Commonly used values are:

  • sAMAccountName (default)
  • userPrincipalName
  • uid

If you pass null as the value of this option, the default UID key is used sAMAccountName.

extra_fields

type: array default: null

Defines the custom fields to pull from the LDAP server. If any field does not exist, an \InvalidArgumentException will be thrown.

filter

type: string default: null

This key lets you configure which LDAP query will be used. The {uid_key} string will be replaced by the value of the uid_key configuration value (by default, sAMAccountName), and the {username} string will be replaced by the username you are trying to load.

For example, with a uid_key of uid, and if you are trying to load the user fabpot, the final string will be: (uid=fabpot).

If you pass null as the value of this option, the default filter is used ({uid_key}={username}).

To prevent LDAP injection, the username will be escaped.

The syntax for the filter key is defined by RFC4515.

Authenticating against an LDAP server

Authenticating against an LDAP server can be done using either the form login or the HTTP Basic authentication providers.

They are configured exactly as their non-LDAP counterparts, with the addition of two configuration keys and one optional key:

service

type: string default: ldap

This is the name of your configured LDAP client. You can freely choose the name, but it must be unique in your application and it cannot start with a number or contain white spaces.

dn_string

type: string default: {username}

This key defines the form of the string used to compose the DN of the user, from the username. The {username} string is replaced by the actual username of the person trying to authenticate.

For example, if your users have DN strings in the form uid=einstein,dc=example,dc=com, then the dn_string will be uid={username},dc=example,dc=com.

query_string

type: string default: null

This (optional) key makes the user provider search for a user and then use the found DN for the bind process. This is useful when using multiple LDAP user providers with different base_dn. The value of this option must be a valid search string (e.g. uid="{username}"). The placeholder value will be replaced by the actual username.

When this option is used, query_string will search in the DN specified by dn_string and the DN resulted of the query_string will be used to authenticate the user with their password. Following the previous example, if your users have the following two DN: dc=companyA,dc=example,dc=com and dc=companyB,dc=example,dc=com, then dn_string should be dc=example,dc=com.

Bear in mind that usernames must be unique across both DN, as the authentication provider won't be able to select the correct user for the bind process if more than one is found.

Examples are provided below, for both form_login_ldap and http_basic_ldap.

Configuration example for form login

1
2
3
4
5
6
7
8
9
10
11
# config/packages/security.yaml
security:
    # ...

    firewalls:
        main:
            # ...
            form_login_ldap:
                # ...
                service: Symfony\Component\Ldap\Ldap
                dn_string: 'uid={username},dc=example,dc=com'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 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="main">
            <form-login-ldap service="Symfony\Component\Ldap\Ldap"
                dn-string="uid={username},dc=example,dc=com"/>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
// config/packages/security.php
use Symfony\Component\Ldap\Ldap;
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->formLoginLdap()
            ->service(Ldap::class)
            ->dnString('uid={username},dc=example,dc=com')
    ;
};

Configuration example for HTTP Basic

1
2
3
4
5
6
7
8
9
10
# config/packages/security.yaml
security:
    # ...

    firewalls:
        main:
            stateless: true
            http_basic_ldap:
                service: Symfony\Component\Ldap\Ldap
                dn_string: 'uid={username},dc=example,dc=com'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 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="main" stateless="true">
            <http-basic-ldap service="Symfony\Component\Ldap\Ldap"
                dn-string="uid={username},dc=example,dc=com"/>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
// config/packages/security.php
use Symfony\Component\Ldap\Ldap;
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->stateless(true)
        ->formLoginLdap()
            ->service(Ldap::class)
            ->dnString('uid={username},dc=example,dc=com')
    ;
};

Configuration example for form login and query_string

1
2
3
4
5
6
7
8
9
10
11
12
13
# config/packages/security.yaml
security:
    # ...

    firewalls:
        main:
            # ...
            form_login_ldap:
                service: Symfony\Component\Ldap\Ldap
                dn_string: 'dc=example,dc=com'
                query_string: '(&(uid={username})(memberOf=cn=users,ou=Services,dc=example,dc=com))'
                search_dn: '...'
                search_password: 'the-raw-password'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 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="main">
            <!-- ... -->
            <form-login-ldap service="Symfony\Component\Ldap\Ldap"
                dn-string="dc=example,dc=com"
                query-string="(&amp;(uid={username})(memberOf=cn=users,ou=Services,dc=example,dc=com))"
                search-dn="..."
                search-password="the-raw-password"/>
        </firewall>
    </config>
</srv:container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// config/packages/security.php
use Symfony\Component\Ldap\Ldap;
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->stateless(true)
        ->formLoginLdap()
            ->service(Ldap::class)
            ->dnString('dc=example,dc=com')
            ->queryString('(&(uid={username})(memberOf=cn=users,ou=Services,dc=example,dc=com))')
            ->searchDn('...')
            ->searchPassword('the-raw-password')
    ;
};
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version
    We stand with Ukraine.
    Version:

    Symfony Security is backed by

    Get your Sylius expertise recognized

    Get your Sylius expertise recognized

    Symfony Code Performance Profiling

    Symfony Code Performance Profiling

    Symfony footer

    ↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

    Avatar of Marichez Pierre, a Symfony contributor

    Thanks Marichez Pierre (@chtipepere) for being a Symfony contributor

    1 commit • 5 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • Symfony at a Glance
      • Symfony Components
      • Case Studies
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • SymfonyConnect
      • Support
      • How to be Involved
      • Code of Conduct
      • Events & Meetups
      • Projects using Symfony
      • Downloads Stats
      • Contributors
      • Backers
    • Blog

      • Events & Meetups
      • A week of symfony
      • Case studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Documentation
      • Living on the edge
      • Releases
      • Security Advisories
      • SymfonyInsight
      • Twig
      • SensioLabs
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Deployed on

    Follow Symfony