{"id":6415,"date":"2020-05-08T19:15:00","date_gmt":"2020-05-09T00:15:00","guid":{"rendered":"https:\/\/www.rushworth.us\/lisa\/?p=6415"},"modified":"2020-05-11T11:11:43","modified_gmt":"2020-05-11T16:11:43","slug":"ldap-authentication-and-authorization-php","status":"publish","type":"post","link":"https:\/\/www.rushworth.us\/lisa\/?p=6415","title":{"rendered":"LDAP Authentication and Authorization: PHP"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Blah<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n&lt;?php\n    error_reporting(0);\n    #=== FUNCTION ==================================================================\n    #      NAME: ldapAuthenticationAndAuthorizationWithAttributes\n    #      PARAMETERS:\n    #                    $strLDAPHost                   String  LDAP Server URI\n    #                    $strUIDAttr                    String  Schema attribute for user ID search\n    #                    $strSystemUser                 String  System credential username\n    #                    $strSystemPassword             String  System credential password\n    #                    $strUserBaseDN                 String  User search LDAP base DN\n    #                    $strLogonUserID                String  Input user ID\n    #                    $strLogonUserPassword          String  Input user password\n    #\t\t\t\t\t $arrayAttrsToReturn\t\t\tString\tAttributes to be returned\n    #                    $strGroupBaseDN                String  (optional) Group search LDAP base DN\n    #                    $strGroupNamingAttribute       String  (optional) Schema attribute for group search\n    #                    $strMembershipAttr             String  (optional) Schema attribute for group membership\n    #                    $strAuthGroup                  String  (optional) Group name\n    #     DESCRIPTION: Verify authentication and authorization against AD server.a\n    #\n    #     RETURNS: array(BindReturnCode, Authorized, array(returnValues))\n    #                        BindReturnCode:    -1 indicates LDAP connection failure, -2 indicates system account auth failed, -3 indicates user auth not attempted, &gt;=0 is IANA-registered resultCode values (https:\/\/www.iana.org\/assignments\/ldap-parameters\/ldap-parameters.xml#ldap-parameters-6)\n    #\t\t\t\t\t\t\tNOTE: 0 is successful authentication in IANA-registered resultCode\n    #                        Authorized:        0 authorization not attempted, -1 is not a member of the located group, 1 is member of the located group\n    #\t\t\t\t\t\tarrayUserAttributeValues\tArray with values of $arrayAttrsToReturn\n    #\n    #     USAGE: $arrayUserAuthorized = ldapAuthenticationAndAuthorizationWithAttributes(&quot;ldaps:\/\/ad.example.com&quot;,&quot;sAMAccountName&quot;,&quot;ldapquery@example.com&quot;, &quot;Sy5t3mP@ssw0rdG03sH3re&quot;, &quot;ou=example,dc=example,dc=com&quot;, $strInputUserName, $strInputUserPassword, array(&#039;givenName&#039;, &#039;sn&#039;), &quot;ou=securitygroups,dc=example,dc=com&quot;,&quot;cn&quot;, &quot;member&quot;, &quot;LJRTestGroup&quot;)\n    #===============================================================================\n    function ldapAuthenticationAndAuthorizationWithAttributes($strLDAPHost,$strUIDAttr, $strSystemUser, $strSystemPassword, $strUserBaseDN, $strLogonUserID, $strLogonUserPassword, $arrayAttrsToReturn, $strGroupBaseDN=null, $strGroupNamingAttribute=null, $strMembershipAttr=null, $strAuthGroup=null){\n        $arrayAuthResults = array();\n        $arrayUserAttributeValues = array();\n        \/\/ Validate password is not null, otherwise directory servers implementing unauthenticated bind (https:\/\/tools.ietf.org\/html\/rfc4513#section-5.1.2) will return 0 on auth attempts with null password\n        if( strlen($strLogonUserPassword) &lt; 1){\n            $arrayAuthResults&#x5B;&#039;BindReturnCode&#039;] = -3;\n            $arrayAuthResults&#x5B;&#039;Authorized&#039;] = -1;\n        }\n        else{\n            \/\/ Connect to the LDAP directory for system ID queries\n            $systemDS = ldap_connect($strLDAPHost);\n            ldap_set_option($systemDS, LDAP_OPT_PROTOCOL_VERSION, 3);\n\n            if ($systemDS) {\n                \/\/ Bind with the system ID and find $strLogonUserID FQDN\n                $systemBind = ldap_bind($systemDS, $strSystemUser, $strSystemPassword);\n\n                if(ldap_errno($systemDS) == 0){\n                    $strLDAPFilter=&quot;(&amp;($strUIDAttr=$strLogonUserID))&quot;;\n                    $result=ldap_search($systemDS,$strUserBaseDN,$strLDAPFilter, $arrayAttrsToReturn);\n\n                    $entry = ldap_first_entry($systemDS, $result);\n\n                    $strFoundUserFQDN= ldap_get_dn($systemDS, $entry);\n\n                    if($strFoundUserFQDN){\n                        $userDS = ldap_connect($strLDAPHost);\n                        ldap_set_option($userDS, LDAP_OPT_PROTOCOL_VERSION, 3);\n\n                        $userBind = ldap_bind($userDS, $strFoundUserFQDN, $strLogonUserPassword);\n                        $arrayAuthResults&#x5B;&#039;BindReturnCode&#039;] = ldap_errno($userDS);\n\n                        ldap_close($userDS);\n\n                        if($arrayAuthResults&#x5B;&#039;BindReturnCode&#039;] == 0){\n                        \t$objFoundUser = ldap_get_entries($systemDS, $result);\n\t\t\t\t\t\t\tfor($arrayAttrsToReturn as $strAttributeName){\n\t\t\t\t\t\t\t\t$arrayUserAttributeValues&#x5B;$strAttributeName] = $objFoundUser&#x5B;0]&#x5B;$strAttributeName];\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$arrayAuthResults&#x5B;&#039;AttributeValues&#039;] = $arrayUserAttributeValues;\n                            \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n                            \/\/ If an auth group has been supplied, verify authorization\n                            \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n                            if($strAuthGroup){\n\t\t\t\t\t\t\t\t\/\/ Escapes in DN need to be double-escaped or bad search filter error is encountered\n                                $strGroupQuery = &quot;(&amp;($strGroupNamingAttribute=$strAuthGroup)($strMembershipAttr=&quot; . str_replace(&quot;\\\\&quot;,&quot;\\\\\\\\&quot;, $strFoundUserFQDN) . &quot;))&quot;;\n\n                                $groupResult = ldap_search($systemDS,$strGroupBaseDN, $strGroupQuery);\n                                $authorisedState = ldap_count_entries($systemDS ,$groupResult);\n\n                                \/\/ If a group matching the filter is found, the user is authorised\n                                if($authorisedState == 1){\n                                    $arrayAuthResults&#x5B;&#039;Authorized&#039;] = 1;\n                                }\n                                \/\/ Otherwise the user is not a member of the group and is not authorised\n                                else{\n                                    $arrayAuthResults&#x5B;&#039;Authorized&#039;] = -1;\n                                }\n                            }\n                            else{\n                                $arrayAuthResults&#x5B;&#039;Authorized&#039;] = 0;\n                            }\n                            \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n                            ldap_close($systemDS);\n                        }\n                        \/\/ If the bind failed, the user has not logged in successfully so they cannot be authorized\n                        else{\n                            $arrayAuthResults&#x5B;&#039;Authorized&#039;] = -1;\n\n                            ldap_close($systemDS);\n                            ldap_close($userDS);\n                        }\n                    }\n                    \/\/ User not found in directory\n                    else{\n                        $arrayAuthResults&#x5B;&#039;BindReturnCode&#039;] = 32;\n                        $arrayAuthResults&#x5B;&#039;Authorized&#039;] = -1;\n                    }\n                }\n                \/\/ system bind failed\n                else{\n                    $arrayAuthResults&#x5B;&#039;BindReturnCode&#039;] = -2;\n                    $arrayAuthResults&#x5B;&#039;Authorized&#039;] = -1;\n                    ldap_close($systemDS);\n                }\n            }\n            \/\/ ldap connection failed\n            else{\n                $arrayAuthResults&#x5B;&#039;BindReturnCode&#039;] = -1;\n                $arrayAuthResults&#x5B;&#039;Authorized&#039;] = -1;\n            }\n        }\n        return $arrayAuthResults;\n    }\n\n    print &quot;User password not supplied:\\n&quot;;\n    $arrayNullPassword = array();\n    $arrayNullPassword = ldapAuthenticationAndAuthorizationWithAttributes(&quot;ldaps:\/\/ad.example.com&quot;,&quot;sAMAccountName&quot;,&quot;ldapquery@example.com&quot;, &quot;Sy5t3mP@ssw0rdG03sH3re&quot;, &quot;ou=example,dc=example,dc=com&quot;, &quot;e0012345&quot;, &#039;&#039;);\n    var_dump($arrayNullPassword);\n\n    print &quot;Bad password:\\n&quot;;\n    $arrayBadPassword = array();\n    $arrayBadPassword = ldapAuthenticationAndAuthorizationWithAttributes(&quot;ldaps:\/\/ad.example.com&quot;,&quot;sAMAccountName&quot;,&quot;ldapquery@example.com&quot;, &quot;Sy5t3mP@ssw0rdG03sH3re&quot;, &quot;ou=example,dc=example,dc=com&quot;, &quot;e0012345&quot;, &#039;N0tTh3P@s5w0rd&#039;,&quot;ou=SecurityGroups,dc=example,dc=com&quot;,&quot;cn&quot;, &quot;member&quot;);\n    var_dump($arrayBadPassword);\n\n    print &quot;\\nInvalid user:\\n&quot;;\n    $arrayUserNotInDirectory = array();\n    $arrayUserNotInDirectory = ldapAuthenticationAndAuthorizationWithAttributes(&quot;ldaps:\/\/ad.example.com&quot;,&quot;sAMAccountName&quot;,&quot;ldapquery@example.com&quot;, &quot;Sy5t3mP@ssw0rdG03sH3re&quot;, &quot;ou=example,dc=example,dc=com&quot;, &quot;xe0012345&quot;, &#039;xDoesN0tM@tt3r&#039;);\n    var_dump($arrayUserNotInDirectory);\n\n    print &quot;\\nGood password without authorization:\\n&quot;;\n    $arrayUserAuthenticated = array();\n    $arrayUserAuthenticated = ldapAuthenticationAndAuthorizationWithAttributes(&quot;ldaps:\/\/ad.example.com&quot;,&quot;sAMAccountName&quot;,&quot;ldapquery@example.com&quot;, &quot;Sy5t3mP@ssw0rdG03sH3re&quot;, &quot;ou=example,dc=example,dc=com&quot;, &quot;e0012345&quot;, &#039;Us3rP@s5w0rdG035H3re|Us3rP@s5w0rdG035H3re&#039;);\n    var_dump($arrayUserAuthenticated);\n\n    print &quot;\\nGood password with authorized user:\\n&quot;;\n    $arrayUserAuthorized = array();\n    $arrayUserAuthorized = ldapAuthenticationAndAuthorizationWithAttributes(&quot;ldaps:\/\/ad.example.com&quot;,&quot;sAMAccountName&quot;,&quot;ldapquery@example.com&quot;, &quot;Sy5t3mP@ssw0rdG03sH3re&quot;, &quot;ou=example,dc=example,dc=com&quot;, &quot;e0012345&quot;, &#039;Us3rP@s5w0rdG035H3re|Us3rP@s5w0rdG035H3re&#039;,&quot;ou=SecurityGroups,dc=example,dc=com&quot;,&quot;cn&quot;, &quot;member&quot;, &quot;cfyP_Unix_UnixUsers&quot;);\n    var_dump($arrayUserAuthorized);\n\n    print &quot;\\nGood password with unauthorized user:\\n&quot;;\n    $arrayUserNotAuthorized = array();\n    $arrayUserNotAuthorized = ldapAuthenticationAndAuthorizationWithAttributes(&quot;ldaps:\/\/ad.example.com&quot;,&quot;sAMAccountName&quot;,&quot;ldapquery@example.com&quot;, &quot;Sy5t3mP@ssw0rdG03sH3re&quot;, &quot;ou=example,dc=example,dc=com&quot;, &quot;e0012345&quot;, &#039;Us3rP@s5w0rdG035H3re|Us3rP@s5w0rdG035H3re&#039;,&quot;ou=SecurityGroups,dc=example,dc=com&quot;,&quot;cn&quot;, &quot;member&quot;, &quot;WIN AM Team West&quot;);\n    var_dump($arrayUserNotAuthorized);\n\n    print &quot;\\nBad system account:\\n&quot;;\n    $arrayBadSystemCred = array();\n    $arrayBadSystemCred = ldapAuthenticationAndAuthorizationWithAttributes(&quot;ldaps:\/\/ad.example.com&quot;,&quot;sAMAccountName&quot;,&quot;ldapquery@example.com&quot;, &quot;xSy5t3mP@ssw0rdG03sH3re&quot;, &quot;ou=example,dc=example,dc=com&quot;, &quot;e0012345&quot;, &#039;Us3rP@s5w0rdG035H3re|Us3rP@s5w0rdG035H3re&#039;);\n    var_dump($arrayBadSystemCred);\n\n?&gt;\n\n<\/pre><\/div>","protected":false},"excerpt":{"rendered":"<p>Blah<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[33],"tags":[295,303],"class_list":["post-6415","post","type-post","status-publish","format-standard","hentry","category-coding","tag-authentication","tag-ldap"],"_links":{"self":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/6415","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6415"}],"version-history":[{"count":2,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/6415\/revisions"}],"predecessor-version":[{"id":6422,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/6415\/revisions\/6422"}],"wp:attachment":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6415"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6415"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6415"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}