PHP login script using LDAP, verify group membership

Simple PHP login script that authenticates through Active Directory using LDAP.  Checks user’s membership against two groups, and assigns permissions to a session variable.

authenticate.php

login.php

protected.php

Update 6/3/2017: Added protected page to illustrate session verification and access check.

208 Comments

  1. Dušek

    Thank you so much code works perfectly. I want to ask how I set the file index.php, and I broke WebUsers WebManagers to each group previewed something else? The division would be carried out through session_start? please advise

        • sam

          There’s a bug with the syntax highlighter plugin I was using

          I have switched plugins temporarily so you should now see both code blocks in the original post

          • tenji

            Sam I would like to lock down pages to a specific set of users, they are members of many different ou’s and I do not want to create a ou as there is only a few people I want to give access to this page. In the $_SESSION[‘user’] statement is there a way to specify =[‘JohnDoe’],[‘JaneDoe’]etc.. if not = then die?

          • sam

            tenji,

            Yes that can be done with simple PHP

            In authenticate(), $_SESSION[‘user’] is already being set

            So– in a higher tiered file (like a config.php), you could do something like:

  2. Dušek

    When you successfully login to index.php, how do I verify a user group?
    index.php
    <?php if($_SESSION['access']=="2" ){
    echo' WebManagers – page for the administrator';}
    <?php if($_SESSION['access']=="1" ){
    echo' WebUsers – page for the users ';}

    how do I set up $_SESSION in index.php

    I am sorry for my English :)

    • sam

      $_SESSION variables will carry over to any page within the PHP installation’s scope – just make sure session_start(); is at the top of the page

      You should probably create a config.php with session_start(); in it

      Then include(‘config.php’); at the top of login.php (above authenticate.php) and at the top of index.php

      config.php

      index.php

      • tenji

        This does not work for me when I browse to a page without logging in it is letting me get into it without redirecting me to login also how can i set session timeout in this script? Please help!

        • sam

          tenji,

          You simply need to check for an existing $_SESSION on protected pages

          For example:

          To make sessions timeout you need to create a new session variable to track the time of last activity

          Consider this code below:

    • sam

      Since everyone’s AD setup is different, there’s no way to provide an ‘out-of-the-box’ working example

      You should be able to select and copy the code for the two files, clicking the magnifying glass icon might make it easier

  3. mark

    Greetings,

    Its always gives me this error. Can anyone help

    Warning: ldap_search() [function.ldap-search]: Search: Operations error in C:\xampp\htdocs\aaa\authenticate.php on line 27
    Unable to search LDAP server

    • sam

      Remove the @ from line 22 before ldap_bind just to see if there’s a helpful error message being suppressed

      And make sure your $ldap_dn is correct

  4. okello

    somehow,this script does not work forme, whether you provide the correct login details or the wrong ones, it continues without an error, something is not ok. Anyone got the same issue?

  5. okello

    to add to the code above, the only change made was on, nothing else

    // Active Directory server
    $ldap_host = “mydomain.com”;
    // Active Directory DN
    $ldap_dn = “OU=user,DC=mydomain,DC=com”;
    // Active Directory user group
    $ldap_user_group = “Users”;
    // Active Directory manager group
    $ldap_manager_group = “Administrators”;
    // Domain, for purposes of constructing $user
    $ldap_usr_dom = “@mydomain.com”;

  6. Rhys

    Hi Sam, thank you very much for the login script it worked very well for me.

    I was wondering how i would display the Username or name and surname of a user from ldap on the index.php page eg Welcome: Peter Owens once they have logged in.

    Thanks.

    • sam

      Rhys,

      You can add any other attributes you want to pull to the array on line 26 of authenticate.php

      Adding CN will get the full name you desire:

      This will produce output like this:

      You can then put the CN result into the session to display it on later pages

        • sam

          I need more information– what are you trying to do/query?

          You can post your code if you’d like (be sure to remove anything sensitive)

          • Pedro Poucel

            Hi, this is my code:
            <?php
            session_start();

            if(isset($_POST["user"]) && isset($_POST["pwd"])){
            $ldaphost = "myhost";
            $ldapport = 389;
            $ldapconn = ldap_connect($ldaphost,$ldapport);
            $user=$_POST["user"];
            $pwd=$_POST["pwd"];
            if($ldapconn){
            echo " You are connected to $ldaphost “;
            ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
            ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);

            $ldapbind=@ldap_bind($ldapconn,$user,$pwd);

            if($ldapbind){
            echo “your user and password are correct, you are connected”;
            $filter=”(sAMAccountName=$user)”;
            $attr=array(“memberof”,”cn”);
            $result = ldap_search($ldapconn,”ou=Im not sure what should go in here, if you could explain me, I would aprecaiate it”,$filter)or exit(“unable to search LDAP server”);
            ldap_sort($ldapconn,$result,”sn”);
            $info = ldap_get_entries($ldapconn, $result);
            ldap_unbind($ldapconn);
            @ldap_close($ldapconn);
            } else {
            $msg = “Invalid email address / password”;
            echo $msg;
            }
            }else{
            echo “Could not connect to $ldaphost”;
            }
            }
            ?>
            My question is, if I want the name to show it in after pages, what do I do? the name like: Welcome Mario Rodriguez
            In advance thanks you, I’m very new to php so whatever extra feedback you have for me, will apreciate it!

          • sam

            Pedro,

            You would store the result in $_SESSION if you want to carry information such as the name over to another page

            You have already started the session with session_start(); so you would set a variable such as $_SESSION[‘name’] = $info[0][‘displayname’][0];
            For more information: http://www.tizag.com/phpT/phpsessions.php

            Also the OU= string in $result is for the DN of the container where all of your users are listed

  7. Ok, so this script out of the box so to speak didn’t work for me, i was getting request error #3 because the $ldap_host variable it appears wasn’t enough to do the ldap_connect with the 2008R2 server, so i added an $ldap_port variable and set that to 389 and changed $ldap = ldap_connect($ldap_host); to

    $ldap = ldap_connect($ldap_host . $ldap.port);

    also I had to change

    $ldap_dn = “OU=Departments,DC=college,DC=school,DC=edu”;

    to

    so OU=Departments was CN=Users as the OU=Users kept failing

    Also this is going to sound stupid but make sure your firewall settings are off when testing, or at least set to allow LDAP lookups from your server. Also if you have just created a user, you need to log in at least once with the user for LDAP to authenticate with the server using that users credentials.

    This is a good script, if you are using apache on linux keep a

    tail -f /var/log/apache2/error.log open so you can see any errors

    Nothing i’m putting here is a negative about the script, it might just help someone..

  8. Mike

    I had to add the following to get this to work:

    ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
    ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0)

    Without it, I was getting:
    PHP Warning: ldap_search(): Search: Operations error in authenticate.php on line 19

  9. Giulius

    Hello Sam,

    this script work great after integrating (+tls) on my structure, but only in the domain the user lives. I have a forest with children domains, and i would like to permit users from others domains to logon (this works) and has right permission.
    Setting groups as universal, from master domain, permitting ldap query, groups membership are not correctly evaluated, and the error is: Invalid argument supplied for foreach().

    Thx.

    • sam

      Hello Giulius,

      This snippet assumes that [‘memberof’] is inside [0] of the array

      It’s likely that there is additional structure in the returning array due to your multiple domain query, provided that your LDAP query parameters are correct

      Unfortunately I don’t have a multiple domain environment to test this in, but you should be able to print_r the $entries array and see what additional structure you will need to take into consideration for picking out memberof

      I hope that helps and sorry I could not be more specific

      • Giulius

        Sam,

        i already did it, Array ( [count] => 0 )
        but this is very strange because authentication works like a charm. I need more investigation.

  10. Giulius

    SAM,

    this is the canges i made to work with children domains and user groups:

    $filter = “(&(objectClass=group)(CN=”.$ldap_user_group.”))”;
    $attr = array(“member”);
    foreach($entries[0][‘member’] as $grps)
    {
    if (strpos($grps, $user))
    $access = 1;
    }

    I needed to reverse the check, because i want to use only 2 groups on parent domain. I think with a little modification you can create for each domain in the forest (admin and user groups) and reuse again memberof instead of member.
    Thx, for your good work with time-saving script … :)

    • tilhan

      Sam,

      How do I add extra ou’s to this code everything works perfect but its only letting me let users in my CN=Users,DC=test,DC=com “Users” ou login just want to add another ou called “test” to be able to login, thanks in advance!

      • sam

        This has been answered further down

        Reduce your $ldap_dn to only DC= and COM=

        Then add these two lines above ldap_bind:

        That should allow you to query the whole DC and catch both containers

  11. guurnita

    Hi,

    i just have some question.:D
    1. What is ‘@’ mean before ldap_bind?
    2. I already try ldap_bind and i always failed if i used username@domain. I just succed when i use full dn like : “cn=admin,ou=people,dc=maxcrc,dc=com”.

    Is there anything that i must to set if i want to use domain?
    Thx.

    • sam

      guurnita,

      1. The @ before ldap_bind is an error control operator. In this case it hides error messages that result from attempting to bind with an invalid username or password- preventing redundant messages. Line 28 of login.php returns a more friendly message to the client. More information here: http://php.net/manual/en/language.operators.errorcontrol.php

      2. The @domain part of the username@domain is a user/account suffix. I am not sure why but it can be required in some environments. If it works without it you should be fine.

  12. Rhys

    Hi Sam,

    I have a bit of a problem with a certain part and was wondering if you may be able to help?

    I have been able to get the script working and the part you helped me with to save the full name for later use, Thanks.

    However one problem I have now is that only one particular user can log on and others users can’t. All of the users are stored in the same place on the server and have the same rights. That is why it does not make sense to me why one user can log on but no other user.

    When I check what is stored in the arrays for the people that can’t gain access then I get the output of. Here is an example not real parameter or names:

    Array ( [count] => 1 [0] => Array ( [cn] => Array ( [count] => 1 [0] => james hill ) [0] => cn [count] => 1 [dn] => CN=james hill,CN=Users,DC=departments,DC=edu ) ).

    However the one particular user can gain access to the webpage. Would you know why this is? And what does the array of the user look like that does gain access.

    Thanks Again..

    Rhys.

    • sam

      Rhys,

      In the example script the login is validated as memberof of one of two groups

      Make sure that the troublesome accounts belong to one of those groups

      Can you paste your code here http://paste.samjlevy.com

      Be sure to replace any sensitive strings with fake information

      And then reply with the URL

      • Rhys

        Hi Sam,

        The code is exactly the same as you have in the two scripts at the top.All I have done it replace the strings with the information I need there.

        At the moment all of my users are in the user group and none are in the manager group even the one user that can gain access. Thats why it makes no sence to me.

        I can’t put a URL up here as the place I am trying to use the script in is in a company intranet that can only be accessed on the premises and not through the internet at the moment.

        Rhys.

        • sam

          Hmm,
          I’m not sure what it could be

          There must be a different setting for the account that works vs the ones that don’t

          I am sorry I cannot be of more help

  13. Hi Sam, i am completely lost. i have developed a php script that works on wamp5 on my system and i need to integrate this script on an intranet but i need to authenticate users on the active directory first. i dont know how to go about it. i have tried different ldap script but none is working. please help me out.

  14. Obiwan

    Hello! Thanks for your script.
    Im trying to connect to a LDAP server W2008 but without sucess.
    Its something missing in w2008 security?
    Tanhaks

    • sam

      It’s hard to say without more details

      Are you getting any errors?

      Try removing @ from the ldap_bind to see if any additional messages are output

      Make sure your DN path is correct

  15. Obiwan

    Hi Sam, thanks for your support.
    In fact my DNS path was not correct. Now I can bind with success, but I’m getting an error related with search: “ldap_search(): Search: Operations error in”.
    Reading a KB in PHP documentation they suggest this directive: “ldap_set_option($ldapconn , LDAP_OPT_REFERRALS,0)”.
    Any suggest?

    • sam

      Your $ldap_dn could still be wrong

      Try adding CN=Users, to the beginning (provided your AD is set up using a Users container)

      Also did you change $filter or $attr? If a mistake is made in there, it could be breaking the LDAP query

  16. gcansecom

    What if i had 2 users in separated OU???,
    example;
    OU=Departments
    OU=Admins

    i can only specify one OU…
    $ldap_dn = “OU=Departments,DC=college,DC=school,DC=edu”;

    How can i search in the entire DN??, or specify various OU.

    Thanks.

    • sam

      gcansecom,

      Leave the “DC=” entries in $ldap_dn

      And then add these below ldap_connect, but above ldap_bind:

  17. RJ

    Hey,

    I have a question about the script. I have been able to login using ldap, but I can’t seem to create any session variables. When I do a  Print_r ($_SESSION); I get an empty array(). Any suggestions to help? I have already tried using config.php with session_start(); in both the login.php and testpage.php.

    Thanks!

    • sam

      Something must still be wrong with the session_start(); placement

      Make sure it is always the first thing being executed

      For example, if it’s in a config.php, make sure the config.php is included above authenticate.php on login.php, and that it is first on index.php (or whatever post-login page the user is redirected to)

  18. RJ

    Per your instruction, I have checked and config.php is indeed included at the top for both the login.php and testpage.php. I have tried passing $_SESSION[‘user’] = “test”; in different parts of the authenticate.php and login.php file, but nothing seems to be passed along. Are there certain things that need to be done server side to allow sessions to be passed between pages?

  19. Jonas

    Hi Sam,
    Great script!

    I’m having a slight issue with the username being displayed after login, it just doesn’t show.. I was also wondering how to validate if the user is logged in or not on any given page, say for instance, if you browse to http://mydomain.com/dashboard.php, it should spit out an error message stating that you must be logged in and direct you to the login page. Is there away to check that a user is logged in?

    • sam

      Make sure your server has PHP sessions turned on

      You can try to print_r($_SESSION); to see if anything is being stored

      That’s how you will verify if someone is logged in or not- if isset($_SESSION[‘user’]) then the user is logged in

  20. Javid

    Hey,

    Thank you very much for the script and it helped me a lot. I am using this script to authenticate every single user for file uploads over the web. Therefore, group verifying wouldn’t really help me since when a user logs in, then he is going to have access to all the directories in that folder. IIS windows authentication is the same story so I was thinking maybe this would help me. Is there a way so that the script can authenticate one user for only one directory?

    Thanks

    Javid

    • sam

      If you don’t need to check group membership, then all you need is to attempt to bind to LDAP

      If bind is successful, the username and password are valid, if not they are invalid

  21. Dan

    Hi Sam, thank about this simple but very effective script. the script work very well but I am trying to add on my current login script and I have issue. I have paste my current script (add_ldap) if you can help me where I can insert your code. thanks for your help in advance.

    • sam

      Dan,

      Unfortunately I don’t have the time to write the code for you. You should be able to add a function to the class named something like ldap_verify with passage of a username/pw to ldap_bind inside of it

      Then replace the database queries in log_in etc with references to ldap_verify

      • Dan

        thanks Sam! great suggestion I will try that way!! I was not expecting to write a code for me, just a suggestion what I should do! :) thanks again!!!

  22. Gus

    Hi Sam.
    I’m having an issue wit the ldap_connect(). It keep saying: Fatal error: Call to undefined function ldap_connect() . Am i doing anything wrong?

    This i have correct:
    // Active Directory server
    $ldap_host = “server”;

    // Active Directory DN
    $ldap_dn = “dc=somthing,dc=int”;

    // Active Directory user group
    $ldap_user_group = “ou=Some, dc=something, dc=int”;

    // Domain, for purposes of constructing $user
    $ldap_usr_dom = “something.int”;

    • sam

      You need to enable the LDAP extension for PHP

      For windows, uncomment the reference to php_ldap.dll in php.ini

      On linux, install php5-ldap, ie:
      sudo apt-get install php5-ldap

  23. Dominik

    Hello there,

    I am trying to use you Auth method for a single group.

    How would that look like?

    So far I have this :

    class LDAPcon {

    private $ldap_host = "domain.lan";
    private $ldap_dn = "OU=group, DC=domain, DC=lan";
    private $groupdn = "group";
    private $ldap_usr_dom = "group.domain.com";

    public function __construct() {
    $this->ldap = ldap_connect($this->ldap_host);
    $this->errorHandler(ldap_errno($this->ldap));
    // For error finding use : $this->errorHandler(ldap_errno($this->ldap);
    }

    /*
    * Bool
    */

    // Test the user credentials
    public function auth($userName, $userPassword) {

    if (@ldap_bind($this->ldap, "Domain\\" . $userName, $userPassword)) {
    $filter = "(sAMAccountName=" . $userName . ")";
    $attr = array("memberOf");
    $result = ldap_search($this->ldap, $this->ldap_dn, $filter, $attr);
    $entries = ldap_get_entries($this->ldap, $result);
    ldap_unbind ($this->ldap);
    if ($entries == $attr) {

    return true;
    } else {
    $this->errorHandler(ldap_errno($this->ldap));
    return false;
    }
    }
    }

  24. Dominik

    Hello Sam!

    I have used the $entries, this was already another exmaple.

    I could not get it to work for a single group.

    Could you give me the example with just either the Manager group or the User group?
    Just to see the code for the single group Auth. That would be great.

    I got it working with the Foreach of the 2 groups giving them both the value of my group, so it would go to either Mygroup or Mygroup, instead of managers and Users. That worked well, but it looks a little messy in the code to have a double $entrie for a single group.

    Thanks in advance! I hope I was able to explain myself somehow correct!

    Greetings!

    • sam

      Dominik,

      The groups that the user belongs to are returned in an array: $entries[0][‘memberof’]

      You need to search or loop through the array and check for the desired group

      Since you are only checking for one group, you could replace the foreach clause with this:

      Where ‘CN=Test Group,CN=Users,DC=ad,DC=dev3’ is the fully qualified name of the group (to shorten or make it prettier you could use a variable)

  25. Hi sam.. I want to make a login but it use for single sign on login with ldap…
    do you have some script to make a single sign on system

  26. Joe

    Hi sam,

    What are these? I do have to set the User group up in LDAP?

    $ldap_user_group = “WebUsers”;
    $ldap_manager_group = “WebManagers”;

    I am currently a member of a group called, for example, “Admin – OnCall”, so does that mean I should set:

    $ldap_user_group = “Admin – OnCall”;

    THanks.

    • sam

      Joe,

      The variable names $ldap_user_group and $ldap_admin_group were used as an example of a common situation where you have a group of users (implies limited rights) and a group of admins (with greater rights)

      So if that’s your situation, you would put the name of your AD admin group in $ldap_admin_group and the user group in $ldap_user group.

      The code is just an example, you must modify it to fit your needs

  27. Lahaul Seth

    Hi,
    I’m totally new to the ldap concept. Can you please explain how this code validates the username and password ? If you can explain in detail it would be of great help ?

    • sam

      The ldap_bind() function attempts to use the parameters username and password to connect to active directory

      If the ldap_bind() returns true, this means the username and password are valid

      The code continues on to run an ldap_search() to find what groups the user is a memberOf– granting either access level 1 or 2 depending on what group the user belongs to

  28. Andrew

    Hey, I have a question, what’s the LDAP set up in your apache configuration? Trying to learn more about LDAP configuration and seeing if my work has theirs set up or if I need to change something.

    • sam

      I have been using LDAP with PHP on IIS, not Apache

      I am not sure that you need any special Apache configuration– as long as the LDAP module is enabled for PHP

      • Andrew

        Well I’ve seen configurations like:

        Deny from all
        AuthType Basic
        AuthBasicProvider ldap
        Order deny,allow
        Allow from all
        AuthLDAPURL ldap://bimi-test.fm.abc-dc.it/ou=people,dc=bimi-test,dc=fm,dc=abc-dc,dc=it?uid?sub
        AuthzLDAPAuthoritative off
        AuthName “Ldap admin”
        require valid-user

        So was curious.

      • Andrew

        err forgot about it

        Deny from all
        AuthType Basic
        AuthBasicProvider ldap
        Order deny,allow
        Allow from all
        AuthLDAPURL ldap://bimi-test.fm.abc-dc.it/ou=people,dc=bimi-test,dc=fm,dc=abc-dc,dc=it?uid?sub
        AuthzLDAPAuthoritative off
        AuthName “Ldap admin”
        require valid-user

      • Andrew

        Damn it, not used to using this form of reply, let’s see if this works.

        Deny from all
        AuthType Basic
        AuthBasicProvider ldap
        Order deny,allow
        Allow from all
        AuthLDAPURL ldap://bimi-test.fm.abc-dc.it/ou=people,dc=bimi-test,dc=fm,dc=abc-dc,dc=it?uid?sub
        AuthzLDAPAuthoritative off
        AuthName "Ldap admin"
        require valid-user

        • sam

          AH ok, LDAP authentication at the web server level

          Sorry I have not tinkered with that– again doing most of my stuff w/ IIS/FastCGI/PHP

  29. SuN

    HI Sam,

    I am using your above code with out any modification & its working … only thing is that
    php session will remember my login id .. if i do logout and again login with same userid and blank password still I am able to get in ..

    Rgds..SuN

    can you pls help me in to this ….

    • sam

      try doing a print_r($_SESSION); after a log out and see what is hanging around

      The session_unset() on line 7 of login.php should be wiping it out

  30. mark

    Hi guys….. do you know where can i find Active Directory user group and Active Directory manager group

    // Active Directory user group
    $ldap_user_group = “WebUsers”;

    // Active Directory manager group
    $ldap_manager_group = “WebManagers”;

    • sam

      mark,

      Those are not built in groups, they were just examples for this script

      You can create a user group and a manager group with names of your choosing

      • mark

        Hi sam
        this is how i create user
        dn: cn=Mark,ou=Users,dc=sample,dc=com
        cn: Mark
        sn: sample
        objectClass: inetOrgPerson
        userPassword: P@ssw0rd
        uid: msample

        can you make sample users and group
        sory i am newbie in ldap

  31. maverick

    Hello,
    I have an application, which i want have AD authentication.
    I create login page which take your code. I redirect it to myapp.php
    I also take your authenticate.php code.
    My question is the following.
    What must I add to myapp.php to use the session and redirect users, which try to directly use the page myapp.php. I want redirect them to login.php if they aren’t authentified, by i don’t know how I must do it. Could you help me? regards

    • sam

      maverick,

      You just need to check for the existence of a session variable to determine if the user is logged in

      • maverick

        Hello,
        I’m blocked on my login page:
        login.php
        <?php
        include("authenticate.php");
        // check to see if user is logging out
        if(isset($_GET['out'])) {
        // destroy session
        session_unset();
        $_SESSION = array();
        unset($_SESSION['user']);
        session_destroy();
        }

        // check to see if login form has been submitted
        if(isset($_POST['userLogin'])){
        // run information through authenticator
        if(authenticate($_POST['userLogin'],$_POST['userPassword']))
        {
        // authentication passed
        header("Location: myapp.php");
        die();
        } else {
        // authentication failed
        $error = 1;
        }
        }

        // output error to user
        if (isset($error)) echo "Erreur: Nom d'utilisateur ou mot de passe incorrect”;

        // output logout success
        if (isset($_GET[‘out’])) echo “Logout successful”;
        ?>
        //my html code

        my page myapp.php

        If i close my navigator or my page, is the session automatically killed?
        I don’t understand why i’m not redirected to my myapp.php page when I logged me in.

  32. Brayan

    Hey , i am creating a web page login within my organization . Ek user has his credentials in AD server which the user uses to log on to his worksation . I need to use this details in my login page where the user uses his workstation credentials to login to my website .

    i have the host name where AD is
    base DN
    User DN
    User pass ……… i need to let users log in with thier credentials , ie on submit , check id and password against the AD and let user in . Where and What changes i should do …

  33. chris

    When using the code, i seem to always get incorrect username and pw. i know the pw is right, so my username must not be right. i have seen it should just be the username, such as abc4, but i have also seen it should be like uid=abc4,ou=People,dn=college,dn=edu. if the server i am trying to connect to is cisunix.unh.edu, what should my username be?
    thanks in advance

  34. BSUK

    Hi Sam, thanks for the script.
    It works amazingly as far as logging in and authenticating etc.

    One thing though: I’m using: if(!isset($_SESSION[‘user’])) die(‘Forbidden’);
    at the top of the page that I want to enforce authentication, and it says “Forbidden” even though I have successfully authenticated?

    Any ideas? Or perhaps I’m missing some extra config?
    Many thanks.

    BSUK.

    • sam

      BSUK make sure you have a session_start(); before your IF statement

      The session needs to be initialized before you can check to see if [‘user’] has been set

      • BSUK

        Perfect, that did it! Many thanks Sam!

        In other news, here’s another bit that may be useful for some folk (found from another site):

        if (!isset($_SESSION[‘user’])) {
        header(‘Location: login.php’);
        }

        This code redirects to the login page if the user isn’t authenticated, rather than just displaying “forbidden”.

  35. Jeremy

    Hi Sam,

    I first want to say that this is an awesome piece of code, first setup I’ve seen that is both functional and relatively easy to implement.

    I do have one question though. While working in my dev environment, I’ve noticed that when I input the incorrect UN or PW, I get the “Login failed” message. However, when I don’t input a UN or PW, I am still able to “login” successfully. I’m relatively new to all of this so I’m sure I’m missing something pretty obvious. Any suggestions on how to correct this or what I might be missing? I’m including the code below:

    Cheers!

    • sam

      Jeremy,

      The authenticate function needs to flag whether the user is valid or not

      In my example above, I use $_SESSION variables to do this

      You would then need to check the existence or value of this flagging variable on your protected pages

      For example:

      A convenient way is to put the above check in a session.php that is included on every page (except login)

  36. Ivo

    hi sam,
    first i wanna say thanx a lot for the script this is an awesome for me to solve my trouble,,,
    but i’ve some trouble again abaut the server, so how can i do if my web server using Linux (CentOS 6.4) ?
    i was try with your code and any code but i can’t :(
    please help,,, thx a lot

    • sam

      Chris,

      SSL is a must for adding security

      To help prevent abuse/password guessing you should have brute force protection such as fail2ban and/or CAPTCHA. I also recommend a custom logging system that records a user’s movements around the protected data.

      As mentioned in some of the comments, this code is only for the login/authenticate actions– you should have a function used at the top of your protected pages that checks for an existing authenticated session in order to kick unauthorized users back to the login page.

      Additionally where possible you want to use .htaccess or IIS restrictions to limit access to the protected site to only those individuals that need it (such as IP/domain restrictions)

      These are just a few suggestions to make it more secure

  37. Peter

    First of all, great script! Second, I’m amazed at your dedication and patience with each and every user. Congrats , Sam and best of wishes!

  38. Matthew Matters

    I can not seem to get it working, when i login it just redirects me to a blank page? no error messages or anything

    • sam

      Matthew,

      This is not a full-featured script, it just shows the basics of running an LDAP query from PHP

      index.php isn’t provided and is assumed to be the protected area of your app– the redirect should not occur unless the login is correct and in the specified group

      If you think errors should be appearing perhaps your error_reporting is turned off in PHP, try adding this to the top of authenticate.php:

  39. Hi, I’m very new to LDAP, I would like to connect to my LDAP server, but I don’t know exactly where I have to add all the information!
    Please can somebody guide me step by step to add the info’s of my server to the right fields. I would appreciate your help thank you in advance.

  40. chimmi


    Notice: Undefined offset: 0 in C:\xampp\htdocs\OIR\authenticate.php on line 35

    Notice: Undefined offset: 0 in C:\xampp\htdocs\OIR\authenticate.php on line 39

    Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\OIR\authenticate.php on line 39

    Notice: Undefined variable: access in C:\xampp\htdocs\OIR\authenticate.php on line 48

    why im having that error in
    1. $givenname = $entries[0][‘givenname’];
    2. foreach($entries[0][‘memberof’] as $grps)
    {
    // is manager, break loop
    // if (strpos($grps, $ldap_manager_group)) { $access = 2; break; }

    // is user
    if (strpos($grps, $ldap_user_group)) $access = 1;
    }
    3. if ($access != 0) {
    // establish session variables
    $_SESSION[‘user’] = $user;
    $_SESSION[‘access’] = $access;
    $_SESSION[‘givenname’] = $givenname;
    return true;
    } else {
    // user has no rights
    return false;
    }

  41. chimmi

    i got that problem.
    now my only problem is even i enter the correct username and password it still says “Login failed: Incorrect user name, password, or rights”.
    what will i change or check the codes ?

    thanks

  42. Great script…excellent comments, just one thing, if i enter a valid username but NO password it still authenticates as a valid user, I currently use a script to check if password box is empty but cannot work out why if $user (only) is valid then treat as authenticated. (should be if $user and $password is valid)

    Thankyou for your time!

  43. sam

    Hi techie2015,

    If password is left blank, ldap_connect attempts to bind anonymously

    If your LDAP server allows anonymous binds you would want to validate that the user-inputted password was not left blank.

    For example you could add:

    To the top of the authenticate function

    I have modified the original snippet above since this is likely a common situation

  44. Thankyou Sam,
    That works great, thankyou for still supporting this article (Which is by far one the best PHP LDAP tutorials i have found), not only have you actively helped people here but you have gone above and beyond by giving clear examples.

    It goes to say something when an article posted 5 years ago is still active!

  45. Mary

    Hi Sam!

    Thanks so much for this! Exactly what I needed. However, I was getting an error:

    Warning: ldap_search(): Search: Bad search filter in C:\xampp\htdocs\login\authenticate.php on line 33
    Unable to search LDAP server

    What do you think causes this error? I really have no idea what to check.

    Thanks in advance!

  46. Pato

    You are the best!!!
    I’ve been reading about RBAC. There are plenty of highly extensible and versatile, but your code is exactly what I need!

  47. gembul

    Hi bro,
    Im newbie in LDAP system, i used to used mysql backend for users management before, now i tried to use LDAP in ubuntu to be a backend, in my case i use “slapd” and “phpldapadmin”, i have domain “kom.wfam” so have dc named “kom” dan “wfam” and also have cn=admin, ou with used setting “Generic: Organizational Unit” named “Groups” and “Users”, ou Group have cn “Admin” and cn “Users” and ou Users have cn “sakha”, and cn “gembul”.
    when tried to input username and password a part of ou “Users” (in my case i’d inputed sakha in username anda sakha password) the system return “Login failed: Incorrect user name, password, or rights” in web. what i missed from my case?

    • sam

      You need to do some debugging of authenticate.php

      Either the binding is failing (due to a DN issue or username/pw issue) or the user is not a member of one of the specified groups

      Start by making sure error_reporting is turned on for your PHP installation (either in php.ini or by using ini_set), then remove the @ from line 27 in $bind = @ldap_bind

      See if you get more information from the error message

  48. newman fertig

    All I’m getting is a combination of a bunch of text on the screen, which shows a lot of the code. Seems like the authenticate.php program starts in the middle of a program. Where is the opening <?php

  49. awesome script man works like charm, just one question; how can i get some information from username like user email, first name , last name, SID ,etc. ?

    • sam

      Hi Newman,

      I have never had the patience for instructional books. The way I learn is to take on a project and then solve issues as I encounter them– using resources online. Start with small/easy projects and then take bigger leaps as you learn. Google searching solves most basic problems, for the more complicated ones Stack Overflow http://stackoverflow.com is incredibly useful

      • Newman Fertig

        Thanks Sam. I like your approach very much, and it is one I also heartily endorse, and was, in fact, how I stumbled on your excellent treatise on LDAP authentication. Cheers, and thank you once again.

  50. VALENTINE

    Hi Sam! I’m trying to use your code but having this error..
    Warning: ldap_search(): Search: No such object in C:\xampp\htdocs\ActiveDirective\authenticate.php on line 44
    Unable to search LDAP server
    Please help me. Below is my code

    Thanks

    • sam

      Try adding these lines below ldap_connect, but above ldap_bind:

      • VALENTINE

        I have added the lines of code but still the same error.
        /////
        connected
        Warning: ldap_search(): Search: No such object in C:\xampp\htdocs\ActiveDirective\authenticate.php on line 47
        Unable to search LDAP server
        ////
        Thank you

        • sam

          Make sure your username format is correct

          When binding to LDAP to conduct a search, the username could be required in one of the following formats:
          jdoe
          DOMAIN\jdoe
          jdoe@domain.com

          Lines 21 and 27 are used to build the username for binding:

          You can finagle these lines to try each of the 3 format examples above

          Additionally remove the @ in front of ldap_bind to get more error information

          • VALENTINE

            Hello Mr Sam!
            This is the error i got when i remove the @ symbol.
            Warning: ldap_bind(): Unable to bind to server: Invalid credentials in C:\xampp\htdocs\ActiveDirective\authenticate.php on line 38
            Login failed: Incorrect user name, password, or rights
            Thank you

  51. John Shaft

    Hello,
    i’m having these errors :
    Notice: Undefined offset: 0 in [ … ]\authenticate.php on line 37
    Warning: Invalid argument supplied for foreach() in [ … ]\authenticate.php on line 37
    Notice: Undefined variable: access in [ … ]\authenticate.php on line 45

    The line 37 is the foreach :
    foreach($entries[0][‘memberof’] as $grps) {

    • sam

      This likely means that the $entries array is blank. No entries are returning that match your LDAP search. Try a print_r($entries) before the foreach. See if you get any results.

      You can also remove the @ symbol in front of ldap_bind() to make sure your connection doesn’t have any errors.

    • sam

      John,

      Also make sure your $ldap_dn is a CN or OU that contains the user you are logging in with

      The $ldap_dn becomes the search location when trying to get the user’s ‘memberof’ attribute

  52. Joe

    Hi Sam,
    Cracking script, just what I needed for a project I’ve been given.

    All is fine apart from one slight issue, if the username has a space in it or a number, ‘Joe Bloggs’ or ‘JoeBloggs1’ i just get a error 500. Php error reporting is on but I’m getting no errors, just the 500. If a user without those items logs in (so just JoeBloggs) then it works fine with no issues.

    Is this something that needs modifying in the script, or is it a ldap or active directory issue?

    Thanks in advance!

    • sam

      Hi Joe,

      In my testing I am able to log in using accounts with numbers. The 500 error is likely a generic response, hiding an underlying PHP error.

      Check the error reporting settings of your server. See if you can further adjust settings (maybe error reporting is being ignored? sometimes for example with IIS you have to enable remote error pages) to output the errors or find Apache/IIS log files to get more information.

  53. Fabian

    Hey Sam, Thank You for this nice script. It works pretty nicely. I have 2 questions:
    1. when connecting/verifying the user why is ldap_unbind in there? I’m thinking that the unbind process should be handled at logout/session_unset(). Is the session not needed while you are still logged in?

    2. After authenticating I am running a shell_exec(‘$command’) which works fine when running a query but fails when I want to make an edit/change on the server which tells me that even though I authenticated using LDAPS, it’s not using those credential to perform the functions, only to authenticate a user and login. Is there a way to tell a session to run as the Elevated user account that logged in?

    • sam

      Hi Fabian,

      1) For purposes of this script, the LDAP connection is only being used to check the user’s password and group. It doesn’t need to remain open once the entry information has been captured.

      2) The scope of the binding via php_ldap does not extend to any shell commands. The shell is a completely different environment. You probably want to do your manipulations using other php_ldap commands like http://php.net/manual/en/function.ldap-modify.php — in which case you would not want to immediately unbind.

  54. Allanian

    Hey Sam, Thank You for this nice script. It works nicely. I have 1 question:
    $ldap_host = “ldap://int.something.corp”;
    $bind = ldap_bind($connect, $ldap_user, $ldap_pass) or exit(“>>No connection for $ldap_host<<");
    Its work, no i need to change int.something.corp for CMM-SGVC.something.something.com.
    int.something.corp – the name of all domain
    CMM-SGVC.something.something.com – my controller domain name.
    How can I do that ? If i do $ldap_host = "ldap:/CMM-SGVC.something.something.com"; – its not work.
    I need only connect to a specific domain controller,
    and then we have several controllers. Sorry for my bad english.

    • sam

      Hi Allanian,

      Do you have any error messages?

      It may also be a port issue, note you can specify a port in ldap_connect($ldap_host,389)

      You can also try adding:

      Above ldap_bind()

      • Allanian

        I use the following code

  55. marouane

    Hi Sam,

    I try to bin server with user DN but it don’t works, i only can bind it with root DN !!
    Error : Incorrect user name, password, or rights

    need help , thanks

  56. Jacob

    Hello Sam,

    Your script is great. I found it years ago and used it with some modifications on a personal project. I am not trying to go back and update my code as I have moved to a new install of ubuntu that is running php version 7 and have run into an issue were I am getting an error on the ladp_search step (ldap_search(): Search: Can’t contact LDAP server) however the ldap_bind step works without issue so I know a connection to the LDAP server can be established.

    Any help your willing to give would be much appreciated.

    • Stefan Beier

      I run into the same issue and i changed just two lines like this:

      as i switched from “$bind = ” inside the if clause, to an external $bind, it worked. Maybe this helps you.

    • sam

      Hmm it seems to be working for me on PHP7,
      It sounds like a protocol issue, try adding this line above the line containing ldap_bind():

  57. Andrew Schmidt

    Sam,
    Give yourself some credit dude. Add a comment with your name and url.
    Nice script Thank you!

    Andrew

  58. Ross

    Hi Sam,

    Looking to see if you can help we are looking to get this to search a member group HR for users that will then allow them to access the page but i keep getting unable to search LDAP error once i sign into the login page ?

    • sam

      There must be something wrong with the search string or ldap DN

      You can remove the @ in front of the ldap_bind to try and get some error reporting

  59. Ricardo

    Hi,

    I’m testing this script and everything seems to work ok but something is wrong. Here is my problem, I created a group for testing and added it to ” $ldap_user_group = ” and everything seems to work cause I try to login with a member group and get no error and try with a non group member and I get an error. The problem is that I can’t deny access to my index.php page, I’ve tested and the server has session support and there is what I have on top of the page before html code:

    And it keeps getting me backup to login.php, What am I missing?

    • sam

      Make sure you have a session_start(); then check for the existence of $_SESSION[‘user’] to confirm if the user is logged in or not

      If the user is not logged in you can do a header(“Location: “); die(); redirect

  60. BP

    Hi Sam,

    Thank you for you code it’s great!
    but if i need to get only manager name of user login. Can i do this? because i get manager name data show like this CN=rosie,OU=AllUser,DC=xyz,DC=local

  61. anjanesh babu

    Thank you very much for the scripts – this is the only one that actually worked on the first try. Well structured code and user friendly site.

      • anjanesh babu

        My d-uh moment : script worked on my dev environment but ran into a blank screen on the prod’ish server. Your helpful response above
        “error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
        ini_set(“display_errors”,1);
        ” revealed that the php-ldap extension was not installed.
        And the session variable setting information is valuable. Basicall; you have provided all the information needed to get someone off the ground and into production in one page.

  62. shweta agarwal

    I want to make a login page in php and validate the user’s name, password and domain from active directory,if such user exists in that AD then redirect on other page and if, user does not exist then display a message user does not exist.

  63. Sean Dela Rosa

    Hi sam,

    Why is it that even though i entered the right username and password, it keeps on saying “Login failed: Incorrect user name, password, or rights”

    • sam

      It’s not finding the group or can’t bind to ldap

      You can try removing the @ in front of ldap_bind and make sure error_reporting is turned on to get more information

  64. Khalid

    Getting the following warning:
    Warning: ldap_search(): Search: Can’t contact LDAP server in C:\xampp\htdocs\dash\authenticate.php on line 32
    Unable to search LDAP server

    Also what should I enter for the following:
    $ldap_dn = ” “;
    $ldap_user_group = “WebUsers”;
    $ldap_manager_group = “WebManagers”;
    Thanks in advance.

  65. Taylor

    Hey Sam,

    Awesome script, it is working great!

    One question for you, how can I create a logout button on a page that destroys the session? I see the code is in the script but I’m not sure what to do to make that part work.

    Your feedback is greatly appreciated!

    • Taylor

      I did more research and figured it out. Just put a button on page that calls the script again with a ?out=true added to the end.

      Logout

      Thanks again for the awesome script!

  66. Lukas

    I have a problem after executing ldap_get_entries, array $entries is null -> Array ( [count] => 0 ).
    What could be wrong? DN is OK, I can login without any errors, but I cannot check rights :(

  67. Patricio IL

    Simple.
    Powerful.
    Great.
    Thanks for sharing Sam!
    Any recommendations to secure the form transmission to avoid man in the middle (sniffer) attacks?
    I’m using https but I wonder what’s the best way to encrypt the password considering that I can’t compare hashes with the actual passwords being stored in the LDAP (AD) server.

  68. hem

    Sam,

    i have one page link to main.php (complerequest.php) I want to give only Active Directory manager group . But main.php can be accessible from both group ( manager group & Active Directory user group) any idea How I do that ..

    • sam

      Hi hem,

      You just need to use a simple IF statement to check the user’s membership on that page (stored in $_SESSION[‘access’]). If they do not have the correct membership you can close the connection with die(); or redirect them somewhere else.

  69. Jun

    Hi Sam
    I got a problem; i login to first user, it Ok but when i login to second user (in different computer) (first user still login) : i use print_r($entries) to show
    Array ( [count] => 1 [0] => Array ( [count] => 0 [dn] => CN=mrk\,ali (HPH),OU=Room,OU=Headquater,OU=City,OU=Head,DC=North,DC=General,DC=Doc ) )
    Warning: Invalid argument supplied for foreach() in D:\WeApp\www\HotelCheck\includes\authenticate.php on line 48
    sorry for my poor English

  70. Hem

    Hi Sam,

    I need to give all user access to Website & I have using below parameters , but its seem not working ?

    // Active Directory user group
    $ldap_user_group = “Domain Users”;

    on other hand if I give some DL name its working .. can you Please let me know how to active this ?

    Regards..Hem

  71. Ryan Holmes

    Hi Sam

    This is a great piece of work you’ve done!
    Thanks

    I wanted to know if you could maybe help me out?

    I have a site build in php/html that allows the User to input answers to the various questions. Upon submit, it then posts the variable input values to my MS SQL server.

    This all works fine, however, I’d like to auto populate the Users Name and Email in automatically. The site is only accessible within the Domain Ip range, and so I was thinking maybe I could use the ldap server to get the attributes i need.

    However all my research had required me to force the User to use a login form first, then display the questionnaire page, and then i could use ldap variables.
    Is there a way, the page could auto authenticate the user without Username and Password input requirements?

    Scenario:
    Windows domain is SAM01DOM01.SAM.COM,
    All users are connected to this domain by default through citrix sessions and domain aligned laptops.
    User opens site address http://www.questionaire.com (local CName record against internal site)
    Page opens, and auto populates:
    Email Address: sessionuser@mail.com,
    User Name: John Doe
    When User clicks submit – all input fields and 2 ldap fields are POST’d to SQL

    Any way I could achieve this?

    Regards

    Ryan

    • sam

      Hi Ryan,

      I believe this is possible if you are using IIS. The ‘Windows Authentication’ module in IIS should allow PHP to access a server variable $_SERVER[‘LOGON_USER’] for retrieving the logged-in user’s AD name

      You would then alter your PHP code to use a pre-made AD account specifically for binding and querying (a “lookup account”) the LOGON_USER’s information to autofill the fields

      This should get you in the right direction: https://stackoverflow.com/questions/26735047/windows-authentication-with-php-on-iis

      Let me know if that ends up working for you

    • sam

      This generally means you don’t have php_ldap.dll extension (if hosting on windows) or php_ldap module (on linux) enabled

      Check the php.ini section under extensions

      • dee

        Hi Sam,
        my requirement is to check the user is in ldap server on not..for me no need to verify the password..help me please

        • sam

          If you don’t need to check a user’s password– then you could use a dedicated LDAP account strictly to bind and search the directory for the desired info

          So instead of passing variables to ldap_bind you would write in an existing account’s info

          Then you can remove all the password input functionality

  72. Jack

    Here is my code and keep getting error code 10, would you be able to take look?

    <?php
    //connecting
    $ad = ldap_connect("ldap://xxxxxxxxxxxx")
    or die("Couldn't connect to AD!");

    if (ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3)) {
    echo "Using LDAPv3″;
    } else {
    echo “Failed to set protocol version to 3”;
    }
    if (ldap_set_option($ad, LDAP_OPT_REFERRALS,0)) {
    echo “Set REFERRALS 0”;
    } else {
    echo “Failed to set REFERRALS 0″;
    }

    //binding
    if($bd = ldap_bind($ad,”administrator@xxxxxxx.com”,”xxxxxxxxxxxxxxx”)
    or die(“Couldn’t bind to AD!”)){
    echo “Bind domain”;
    } else {
    echo “Bind domain failed”;
    }

    /*
    below is the part of code that I use to add user.

    Here is the result
    Warning: ldap_add() [function.ldap-add]: Add: Operations error in
    …/ldaptest.php on line …
    There is a problem to create the account
    Please contact your administrator !
    LDAP-Errno: 1
    LDAP-Error: Operations error

    and the code:
    */

    $adduserAD[“cn”][0] = “test”;
    $adduserAD[“instancetype”][0] = “4”;
    $adduserAD[“samaccountname”][0] = “test”;
    $adduserAD[“objectclass”][0] = “top”;
    $adduserAD[“objectclass”][1] = “person”;
    $adduserAD[“objectclass”][2] = “organizationalPerson”;
    $adduserAD[“objectclass”][3] = “user”;
    $adduserAD[“displayname”][0] = “test”;
    $adduserAD[“name”][0] = “Test”;
    $adduserAD[“givenname”][0] = “Test”;
    $adduserAD[“sn”][0] = “Test”;
    $adduserAD[“company”][0] = “Test”;
    $adduserAD[“department”][0] = “Test”;
    $adduserAD[“title”][0] = “Test”;
    $adduserAD[“description”][0] = “bka”;
    $adduserAD[“mail”][0] = “bla@test.com”;
    $adduserAD[“initials”][0] = “T”;
    $adduserAD[“userprincipalname”][0] = “test”;

    if (!(ldap_add($ad,”CN=test,OU=Users,DC=domain”,$adduserAD))){
    echo “There is a problem to create the account”;
    echo “Please contact your administrator !”;
    echo “LDAP-Errno: ” . ldap_errno($ad) . “”;
    echo “LDAP-Error: ” . ldap_error($ad) . “”;
    exit;
    }

    /*
    here is the part of the code that I use to remove user and its works
    $dn = “CN=test,CN=Users,DC=domain”;
    $result = ldap_delete($ad, $dn);
    if ($result) {echo “User deleted!”;}
    else {echo “There was a problem!”;}
    */

    ?>

Leave a Reply

Your email address will not be published. Required fields are marked *