Search code examples
phpsymfonyactive-directoryldapsymfony3.x

Connect/Bind to Active Directory (Windows) using LDAP in Symfony 3 without using a dn string


I am attempting to authenticate users at my company for Symfony3 apps using Active Directory. My current configuration is as follows (this was also successfully tested with an online LDAP test server so I can confirm the Symfony config is correct).

//services.yml

Symfony\Component\Ldap\Ldap:
        arguments: ['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
    Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
        arguments:
            -   host: host.dom1.dom2.net
                port: 389
                encryption: none
                options:
                    protocol_version: 3
                    referrals: false
//security.yml

my_ldap:
      ldap:
         service: Symfony\Component\Ldap\Ldap
         base_dn: dc=dom1,dc=dom2,dc=net
         search_dn: "cn=myUsername,dc=dom1,dc=dom2,dc=net"
         search_password: myPassword
         default_roles: ROLE_ADMIN
         uid_key: sAMAccountName

....
firewalls:
      form_login_ldap:
         provider: my_ldap
         service: Symfony\Component\Ldap\Ldap
         dn_string: 'sAMAccountName={username},dc=dom1,dc=dom2,dc=net'
         login_path: login
         check_path: login
         default_target_path: /index

When I attempt to login, I will get denied based on "invalid credentials" while I am sure my credentials are being entered correctly. I am hoping the main issue here is that the "search_dn" & "search_password" are my own, and I do not have admin rights in our AD. It appears (according to the Symfony documentation) these creds need to be that of an AD admin user. I am waiting on this info from my sysadmin but it had to go up the chain so it may take a while. I tried replacing them both with nulls as well which throws a different error.

My question comes in at this point as I actually am able to establish a successful connection & bind with our AD using PHP alone with the following code:

//ldapconnect.php

$ldap = ldap_connect("host.dom1.dom2.net");

if (ldap_bind($ldap, "[email protected]", "myPassword")) {
    echo "login successful";
 } else {
    echo "Incorrect Login";
}

Basically I am looking to see if I can somehow replicate the above standalone PHP ldap bind code into my Symfony project (it seems that the dn string required in Symfony is causing the problem). I am fairly new to this so I cannot quite understand why the standalone PHP code allows the LDAP bind while using the dn string does not (other than our AD is possibly blocking the request when dn string used).

Thank you in advance for any assistance.

Edit: updated with read-only-admin search dn info:

//security.yml

my_ldap:
      ldap:
         service: Symfony\Component\Ldap\Ldap
         base_dn: 'CN=Users,dc=dom1,dc=dom2,dc=net'
         search_dn: "cn=ReadOnlyAdmin,OU=ou1,OU=ou2,dc=dom1,dc=dom2,dc=net"
         search_password: adminPass
         default_roles: ROLE_USER
         uid_key: sAMAccountName
....
firewalls:
      http_basic_ldap:
         provider: my_ldap
         service: Symfony\Component\Ldap\Ldap
         dn_string: 'DOMAIN\{username}'

It appears that I am at least able to bind to the ldap server now, however I am still getting invalid credentials with "user not found" error:

//dev.log

[2017-09-11 13:10:15] request.INFO: Matched route "app_default_admin". {"route":"app_default_admin","route_parameters":{"_controller":"AppBundle\\Controller\\DefaultController::adminAction","_route":"app_default_admin"},"request_uri":"http://localhost:8000/index","method":"GET"} []
[2017-09-11 13:10:15] security.INFO: Basic authentication Authorization header found for user. {"username":"myUsername"} []
[2017-09-11 13:10:15] security.INFO: Basic authentication failed for user. {"username":"myUsername","exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\BadCredentialsException(code: 0): Bad credentials. at C:\\pathtoSymfonyProject\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\Security\\Core\\Authentication\\Provider\\UserAuthenticationProvider.php:73, Symfony\\Component\\Security\\Core\\Exception\\UsernameNotFoundException(code: 0): User \"myUsername\" not found. at C:\\pathtoSymfonyProject\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\Security\\Core\\User\\LdapUserProvider.php:82)"} []

I am also questioning this "User \"myUsername\" not found" error toward the end of the third line, is it searching the AD for username "myUsername\" and adding a backslash? This could just be the format of the error code as it looks to be correct in the second line and beginning of the third line.

Edit 2:

I finally got the connection working, the correct config is as follows:

//security.yml

my_ldap:
      ldap:
         service: Symfony\Component\Ldap\Ldap
         base_dn: 'dc=dom1,dc=dom2,dc=net'
         search_dn: "cn=ReadOnlyAdmin,OU=ou1,OU=ou2,dc=dom1,dc=dom2,dc=net"
         search_password: 'adminPass'
         default_roles: ROLE_USER
         uid_key: sAMAccountName
....
firewalls:
      http_basic_ldap:
         provider: my_ldap
         service: Symfony\Component\Ldap\Ldap
         dn_string: 'MYDOMAIN\{username}'

From my previous edit, all that I had to do was remove "CN=Users" from the base_dn as the user accounts were not actually located there, removing that and just leaving the domain components allowed our whole AD to be searched for the user. Another important note is that the dn_string must configured as 'MYDOMAIN\{username}' or the authentication will not go through (per Alvin Bunk's response). As Alvin points out in his article linked below, that part is unfortunately not mentioned in the Symfony LDAP documentation.


Solution

  • Take a look at my recent article on this:

    https://alvinbunk.wordpress.com/2017/09/07/symfony-ldap-component-ad-authentication/

    I suspect you just need to change your dn_string like so:

    dn_string: 'DOMAIN\{username}'
    

    Please read my article. Also try:

    default_roles: ROLE_USER
    

    You can also try using http_basic_ldap as per my article and check the dev log. It's probably something simple - don't give up!