diff --git a/components/index.rst b/components/index.rst index 43aa14e5e40..620fbc239d7 100644 --- a/components/index.rst +++ b/components/index.rst @@ -22,6 +22,7 @@ The Components http_foundation/index http_kernel/index intl + ldap options_resolver phpunit_bridge process diff --git a/components/ldap.rst b/components/ldap.rst new file mode 100644 index 00000000000..b1f51043dd4 --- /dev/null +++ b/components/ldap.rst @@ -0,0 +1,72 @@ +.. index:: + single: Ldap + single: Components; Ldap + +The Ldap Component +================== + + The Ldap component provides a means to connect to an LDAP server (OpenLDAP or Active Directory). + +Installation +------------ + +You can install the component in 2 different ways: + +* :doc:`Install it via Composer ` (``symfony/ldap`` on `Packagist`_); +* Use the official Git repository (https://github.com/symfony/ldap). + +.. include:: /components/require_autoload.rst.inc + +Usage +----- + +The :class:`Symfony\\Component\\Ldap\\LdapClient` class provides methods +to authenticate and query against an LDAP server. + +The :class:`Symfony\\Component\\Ldap\\LdapClient` class can be configured +using the following options: + +``host`` + IP or hostname of the LDAP server + +``port`` + Port used to access the LDAP server + +``version`` + The version of the LDAP protocol to use + +``useSsl`` + Whether or not to secure the connection using SSL + +``useStartTls`` + Whether or not to secure the connection using StartTLS + +``optReferrals`` + Specifies whether to automatically follow referrals + returned by the LDAP server + +For example, to connect to a start-TLS secured LDAP server:: + + use Symfony\Component\Ldap\LdapClient; + + $ldap = new LdapClient('my-server', 389, 3, false, true); + +The :method:`Symfony\\Component\\Ldap\\LdapClient::bind` method +authenticates a previously configured connection using both the +distinguished name (DN) and the password of a user:: + + use Symfony\Component\Ldap\LdapClient; + // ... + + $ldap->bind($dn, $password); + +Once bound (or if you enabled anonymous authentication on your +LDAP server), you may query the LDAP server using the +:method:`Symfony\\Component\\Ldap\\LdapClient::find` method:: + + use Symfony\Component\Ldap\LdapClient; + // ... + + $ldap->find('dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))'); + +.. _Packagist: https://packagist.org/packages/symfony/ldap diff --git a/components/map.rst.inc b/components/map.rst.inc index deb5d6b84c8..2bcd97e9df2 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -112,6 +112,10 @@ * :doc:`/components/intl` +* **Ldap** + + * :doc:`/components/ldap` + * **OptionsResolver** * :doc:`/components/options_resolver` diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 2b56dfa5ec8..a3329a29d0c 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -164,6 +164,7 @@ * :doc:`Security Authentication (Identifying/Logging in the User) ` * :doc:`/cookbook/security/form_login_setup` + * :doc:`/cookbook/security/ldap` * :doc:`/cookbook/security/entity_provider` * :doc:`/cookbook/security/guard-authentication` * :doc:`/cookbook/security/remember_me` diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index 61efff1aa23..44778bc227e 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -8,6 +8,7 @@ Authentication (Identifying/Logging in the User) :maxdepth: 2 form_login_setup + ldap entity_provider guard-authentication remember_me diff --git a/cookbook/security/ldap.rst b/cookbook/security/ldap.rst new file mode 100644 index 00000000000..8d197dbc72a --- /dev/null +++ b/cookbook/security/ldap.rst @@ -0,0 +1,384 @@ +.. index:: + single: Security; Authenticating against an LDAP server + +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 + :class:`Symfony\\Component\\Security\\Core\\User\\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). + +Ldap Configuration Reference +---------------------------- + +See :doc:`/reference/configuration/security` 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 simply configured, using the following service +definition: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/services.yml + services: + ldap: + class: 'Symfony\Component\Ldap\LdapClient' + arguments: + - my-server # host + - 389 # port + - 3 # version + - false # SSL + - true # TLS + + .. code-block:: xml + + + + + + + + my-server + 389 + 3 + false + true + + + + + .. code-block:: php + + // app/config/services.php + $container + ->register('ldap', 'Symfony\Component\Ldap\LdapClient') + ->addArgument('my-server') + ->addArgument(389) + ->addArgument(3) + ->addArgument(false) + ->addArgument(true); + + $container + ->register('newsletter_manager', 'NewsletterManager') + ->addMethodCall('setMailer', array(new Reference('mailer'))); + +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. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + # ... + + providers: + my_ldap: + ldap: + service: 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 + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: php + + $container->loadFromExtension('security', array( + 'providers' => array( + 'ldap_users' => array( + 'ldap' => array( + 'service' => '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', + ), + ), + ), + ); + +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 chose 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 in order to fetch the user's information. + +search_password +............... + +**type**: ``string`` **default**: ``null`` + +This is your read-only user's password, wich will be used to authenticate +against the LDAP server in order 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**: ``sAMAccountName`` + +This is the entry's key to use as its UID. Depends on your LDAP server +implementation. Commonly used values are: + +* ``sAMAccountName`` +* ``userPrincipalName`` +* ``uid`` + +filter +...... + +**type**: ``string`` **default**: ``({uid_key}={username})`` + +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)``. + +Of course, the username will be escaped, in order to prevent `LDAP injection`_. + +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: + +service +....... + +**type**: ``string`` **default**: ``ldap`` + +This is the name of your configured LDAP client. You can freely chose 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 in order 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``. + +Examples are provided below, for both ``form_login_ldap`` and +``http_basic_ldap``. + +Configuration example for form login +.................................... + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + # ... + + firewalls: + main: + # ... + form_login_ldap: + login_path: login + login_check: login_check + # ... + service: ldap + dn_string: 'uid={username},dc=example,dc=com' + + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: php + + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'main' => array( + 'form_login_ldap' => array( + 'login_path' => 'login', + 'login_check' => 'login_check', + 'service' => 'ldap', + 'dn_string' => 'uid={username},dc=example,dc=com', + // ... + ), + ), + ) + ); + +Configuration example for HTTP Basic +.................................... + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + # ... + + firewalls: + main: + # ... + http_basic_ldap: + # ... + service: ldap + dn_string: 'uid={username},dc=example,dc=com' + + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: php + + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'main' => array( + 'http_basic_ldap' => array( + 'service' => 'ldap', + 'dn_string' => 'uid={username},dc=example,dc=com', + // ... + ), + 'stateless' => true, + ), + ), + ); + +.. _`RFC4515`: http://www.faqs.org/rfcs/rfc4515.html +.. _`LDAP injection`: http://projects.webappsec.org/w/page/13246947/LDAP%20Injection diff --git a/reference/configuration/security.rst b/reference/configuration/security.rst index c3e723cf487..69f3cb861fe 100644 --- a/reference/configuration/security.rst +++ b/reference/configuration/security.rst @@ -99,6 +99,16 @@ Each part will be explained in the next section. # name of a non-default entity manager manager_name: ~ + my_ldap_provider: + ldap: + service: ~ + base_dn: ~ + search_dn: ~ + search_password: ~ + default_roles: 'ROLE_USER' + uid_key: 'sAMAccountName' + filter: '({uid_key}={username})' + # Example custom provider my_some_custom_provider: id: ~ @@ -131,6 +141,10 @@ Each part will be explained in the next section. provider: some_key_from_above http_basic: provider: some_key_from_above + http_basic_ldap: + provider: some_key_from_above + service: ldap + dn_string: '{username}' http_digest: provider: some_key_from_above guard: @@ -183,6 +197,50 @@ Each part will be explained in the next section. # new in Symfony 2.3 require_previous_session: true + form_login_ldap: + # submit the login form here + check_path: /login_check + + # the user is redirected here when they need to log in + login_path: /login + + # if true, forward the user to the login form instead of redirecting + use_forward: false + + # login success redirecting options (read further below) + always_use_default_target_path: false + default_target_path: / + target_path_parameter: _target_path + use_referer: false + + # login failure redirecting options (read further below) + failure_path: /foo + failure_forward: false + failure_path_parameter: _failure_path + failure_handler: some.service.id + success_handler: some.service.id + + # field names for the username and password fields + username_parameter: _username + password_parameter: _password + + # csrf token options + csrf_parameter: _csrf_token + csrf_token_id: authenticate + csrf_token_generator: my.csrf_token_generator.id + + # by default, the login form *must* be a POST, not a GET + post_only: true + remember_me: false + + # by default, a session must exist before submitting an authentication request + # if false, then Request::hasPreviousSession is not called during authentication + # new in Symfony 2.3 + require_previous_session: true + + service: ~ + dn_string: '{username}' + remember_me: token_provider: name secret: "%secret%" @@ -255,6 +313,13 @@ Each part will be explained in the next section. The ``secret`` option of ``anonymous`` and ``remember_me`` was introduced in Symfony 2.8. Prior to 2.8, it was called ``key``. +.. versionadded:: 2.8 + The ``http_basic_ldap`` and ``form_login_ldap`` authentication providers + were introduced in Symfony 2.8. + +.. versionadded:: 2.8 + The ``ldap`` user provider was introduced in Symfony 2.8 + .. _reference-security-firewall-form-login: Form Login Configuration @@ -354,6 +419,72 @@ The ``invalidate_session`` option allows to redefine this behavior. Set this option to ``false`` in every firewall and the user will only be logged out from the current firewall and not the other ones. +.. _reference-security-ldap: + +LDAP functionality +------------------ + +There are several options for connecting against an LDAP server, +using the ``form_login_ldap`` and ``http_basic_ldap`` authentication +providers or the ``ldap`` user provider. + +For even more details, see :doc:`/cookbook/security/ldap`. + +Authentication +~~~~~~~~~~~~~~ + +You can authenticate to an LDAP server using the LDAP variants of the +``form_login`` and ``http_basic`` authentication providers. Simply use +``form_login_ldap`` and ``http_basic_ldap``, which will attempt to +``bind`` against a LDAP server instead of using password comparison. + +Both authentication providers have the same arguments as their normal +counterparts, with the addition of two configuration keys: + +service +....... + +**type**: ``string`` **default**: ``ldap`` + +This is the name of your configured LDAP client. + +dn_string +......... + +**type**: ``string`` **default**: ``{username}`` + +This is the string which will be used as the bind DN. The ``{username}`` +placeholder will be replaced with the user-provided value (his login). +Depending on your LDAP server's configuration, you may need to override +this value. + +User provider +~~~~~~~~~~~~~ + +Users will still be fetched from the configured user provider. If you +wish to fetch your users from a LDAP server, you will need to use the +``ldap`` user provider, in addition to one of the two authentication +providers (``form_login_ldap`` or ``http_basic_ldap``). + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + # ... + + providers: + my_ldap_users: + ldap: + service: ldap + base_dn: 'dc=symfony,dc=com' + search_dn: '%ldap.search_dn%' + search_password: '%ldap.search_password%' + default_roles: '' + uid_key: 'uid' + filter: '(&({uid_key}={username})(objectclass=person)(ou=Users))' + Using the PBKDF2 Encoder: Security and Speed --------------------------------------------