diff --git a/lib/SimpleSAML/Auth/LDAP.php b/lib/SimpleSAML/Auth/LDAP.php
index 3a3679d7e493641b1af24c221eb43362f3d6300b..f8a56ebf5f32eb21ac46070fae87fd617f1ded46 100644
--- a/lib/SimpleSAML/Auth/LDAP.php
+++ b/lib/SimpleSAML/Auth/LDAP.php
@@ -22,9 +22,8 @@ if (!defined('LDAP_OPT_DIAGNOSTIC_MESSAGE')) {
  * @author Anders Lund, UNINETT AS. <anders.lund@uninett.no>
  * @package SimpleSAMLphp
  */
-class SimpleSAML_Auth_LDAP {
-
-
+class SimpleSAML_Auth_LDAP
+{
     /**
      * LDAP link identifier.
      *
@@ -55,7 +54,8 @@ class SimpleSAML_Auth_LDAP {
      * @param bool $referrals
      */
     // TODO: Flesh out documentation
-    public function __construct($hostname, $enable_tls = TRUE, $debug = FALSE, $timeout = 0, $port = 389, $referrals = TRUE) {
+    public function __construct($hostname, $enable_tls = true, $debug = false, $timeout = 0, $port = 389, $referrals = true)
+    {
 
         // Debug
         SimpleSAML\Logger::debug('Library - LDAP __construct(): Setup LDAP with ' .
@@ -71,7 +71,7 @@ class SimpleSAML_Auth_LDAP {
          *
          * OpenLDAP 2.x.x or Netscape Directory SDK x.x needed for this option.
          */
-        if ($debug && !ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7)) {
+        if ($debug && !ldap_set_option(null, LDAP_OPT_DEBUG_LEVEL, 7)) {
                 SimpleSAML\Logger::warning('Library - LDAP __construct(): Unable to set debug level (LDAP_OPT_DEBUG_LEVEL) to 7');
         }
 
@@ -80,7 +80,7 @@ class SimpleSAML_Auth_LDAP {
          * doesn't actually connect to the server.
          */
         $this->ldap = @ldap_connect($hostname, $port);
-        if ($this->ldap === FALSE) {
+        if ($this->ldap === false) {
             throw $this->makeException('Library - LDAP __construct(): Unable to connect to \'' . $hostname . '\'', ERR_INTERNAL);
         }
 
@@ -107,7 +107,7 @@ class SimpleSAML_Auth_LDAP {
         }
 
         // Enable TLS, if needed
-        if (stripos($hostname, "ldaps:") === FALSE and $enable_tls) {
+        if (stripos($hostname, "ldaps:") === false and $enable_tls) {
             if (!@ldap_start_tls($this->ldap)) {
                 throw $this->makeException('Library - LDAP __construct(): Unable to force TLS', ERR_INTERNAL);
             }
@@ -123,7 +123,8 @@ class SimpleSAML_Auth_LDAP {
      * The exception's description
      * @return Exception
      */
-    private function makeException($description, $type = NULL) {
+    private function makeException($description, $type = null)
+    {
         $errNo = 0x00;
 
         // Log LDAP code and description, if possible
@@ -200,21 +201,21 @@ class SimpleSAML_Auth_LDAP {
      * - Failed to get first entry from result
      * - Failed to get DN for entry
      * @throws SimpleSAML_Error_UserNotFound if:
-     * - Zero entries was found
+     * - Zero entries were found
      */
-    private function search($base, $attribute, $value, $searchFilter=NULL) {
-
+    private function search($base, $attribute, $value, $searchFilter = null)
+    {
         // Create the search filter
-        $attribute = self::escape_filter_value($attribute, FALSE);
+        $attribute = self::escape_filter_value($attribute, false);
         $value = self::escape_filter_value($value);
         $filter = '';
-        foreach ($attribute AS $attr) {
+        foreach ($attribute as $attr) {
             $filter .= '(' . $attr . '=' . $value. ')';
         }
         $filter = '(|' . $filter . ')';
 
         // Append LDAP filters if defined
-        if ($searchFilter!=NULL) {
+        if ($searchFilter != null) {
             $filter = "(&".$filter."".$searchFilter.")";
         }
 
@@ -222,13 +223,13 @@ class SimpleSAML_Auth_LDAP {
         SimpleSAML\Logger::debug('Library - LDAP search(): Searching base \'' . $base . '\' for \'' . $filter . '\'');
         // TODO: Should aliases be dereferenced?
         $result = @ldap_search($this->ldap, $base, $filter, array(), 0, 0, $this->timeout);
-        if ($result === FALSE) {
+        if ($result === false) {
             throw $this->makeException('Library - LDAP search(): Failed search on base \'' . $base . '\' for \'' . $filter . '\'');
         }
 
         // Sanity checks on search results
         $count = @ldap_count_entries($this->ldap, $result);
-        if ($count === FALSE) {
+        if ($count === false) {
             throw $this->makeException('Library - LDAP search(): Failed to get number of entries returned');
         } elseif ($count > 1) {
             // More than one entry is found. External error
@@ -241,11 +242,11 @@ class SimpleSAML_Auth_LDAP {
 
         // Resolve the DN from the search result
         $entry = @ldap_first_entry($this->ldap, $result);
-        if ($entry === FALSE) {
+        if ($entry === false) {
             throw $this->makeException('Library - LDAP search(): Unable to retrieve result after searching base \'' . $base . '\' for \'' . $filter . '\'');
         }
         $dn = @ldap_get_dn($this->ldap, $entry);
-        if ($dn === FALSE) {
+        if ($dn === false) {
             throw $this->makeException('Library - LDAP search(): Unable to get DN after searching base \'' . $base . '\' for \'' . $filter . '\'');
         }
         // FIXME: Are we now sure, if no excepton has been thrown, that we are returning a DN?
@@ -273,15 +274,15 @@ class SimpleSAML_Auth_LDAP {
      * - LDAP search encounter some problems when searching cataloge
      * - Not able to connect to LDAP server
      * @throws SimpleSAML_Error_UserNotFound if:
-     * - $allowZeroHits er TRUE and no result is found
+     * - $allowZeroHits is FALSE and no result is found
      *
      */
-    public function searchfordn($base, $attribute, $value, $allowZeroHits = FALSE, $searchFilter = NULL) {
-
+    public function searchfordn($base, $attribute, $value, $allowZeroHits = false, $searchFilter = null)
+    {
         // Traverse all search bases, returning DN if found
         $bases = SimpleSAML\Utils\Arrays::arrayize($base);
-        $result = NULL;
-        foreach ($bases AS $current) {
+        $result = null;
+        foreach ($bases as $current) {
             try {
                 // Single base search
                 $result = $this->search($current, $attribute, $value, $searchFilter);
@@ -299,7 +300,7 @@ class SimpleSAML_Auth_LDAP {
         SimpleSAML\Logger::debug('Library - LDAP searchfordn(): No entries found');
         if ($allowZeroHits) {
             // Zero hits allowed
-            return NULL;
+            return null;
         } else {
             // Zero hits not allowed
             throw $this->makeException('Library - LDAP searchfordn(): LDAP search returned zero entries for filter \'(' .
@@ -320,11 +321,11 @@ class SimpleSAML_Auth_LDAP {
      * @param bool $escape Weather to escape the filter values or not
      * @return array
      */
-    public function searchformultiple($bases, $filters, $attributes = array(), $and = TRUE, $escape = TRUE) {
-
+    public function searchformultiple($bases, $filters, $attributes = array(), $and = true, $escape = true)
+    {
         // Escape the filter values, if requested
         if ($escape) {
-            $filters = $this->escape_filter_value($filters, FALSE);
+            $filters = $this->escape_filter_value($filters, false);
         }
 
         // Build search filter
@@ -352,16 +353,16 @@ class SimpleSAML_Auth_LDAP {
         }
 
         // Search each base until result is found
-        $result = FALSE;
+        $result = false;
         foreach ($bases as $base) {
             $result = @ldap_search($this->ldap, $base, $filter, $attributes, 0, 0, $this->timeout);
-            if ($result !== FALSE) {
-            	break;
+            if ($result !== false) {
+                break;
             }
         }
 
         // Verify that a result was found in one of the bases
-        if ($result === FALSE) {
+        if ($result === false) {
             throw $this->makeException(
                 'ldap:LdapConnection->search_manual : Failed to search LDAP using base(s) [' .
                 implode('; ', $bases) . '] with filter [' . $filter . ']. LDAP error [' .
@@ -377,7 +378,7 @@ class SimpleSAML_Auth_LDAP {
 
         // Get all results
         $results = ldap_get_entries($this->ldap, $result);
-        if ($results === FALSE) {
+        if ($results === false) {
             throw $this->makeException(
                 'ldap:LdapConnection->search_manual : Unable to retrieve entries from search results'
             );
@@ -424,10 +425,11 @@ class SimpleSAML_Auth_LDAP {
      * LDAP_INAPPROPRIATE_AUTH, LDAP_INSUFFICIENT_ACCESS
      * @throws SimpleSAML_Error_Exception on other errors
      */
-    public function bind($dn, $password, array $sasl_args = NULL) {
+    public function bind($dn, $password, array $sasl_args = null)
+    {
         $authz_id = null;
 
-        if ($sasl_args != NULL) {
+        if ($sasl_args != null) {
             if (!function_exists('ldap_sasl_bind')) {
                 $ex_msg = 'Library - missing SASL support';
                 throw $this->makeException($ex_msg);
@@ -447,26 +449,26 @@ class SimpleSAML_Auth_LDAP {
             $error = @ldap_bind($this->ldap, $dn, $password);
         }
 
-        if ($error === TRUE) {
+        if ($error === true) {
             // Good
             $this->authz_id = $authz_id;
             SimpleSAML\Logger::debug('Library - LDAP bind(): Bind successful with DN \'' . $dn . '\'');
-            return TRUE;
+            return true;
         }
 
         /* Handle errors
          * LDAP_INVALID_CREDENTIALS
          * LDAP_INSUFFICIENT_ACCESS */
-        switch(ldap_errno($this->ldap)) {
-            case 32:	// LDAP_NO_SUCH_OBJECT
+        switch (ldap_errno($this->ldap)) {
+            case 32: // LDAP_NO_SUCH_OBJECT
                 // no break
-            case 47:	// LDAP_X_PROXY_AUTHZ_FAILURE
+            case 47: // LDAP_X_PROXY_AUTHZ_FAILURE
                 // no break
-            case 48:	// LDAP_INAPPROPRIATE_AUTH
+            case 48: // LDAP_INAPPROPRIATE_AUTH
                 // no break
-            case 49:	// LDAP_INVALID_CREDENTIALS
+            case 49: // LDAP_INVALID_CREDENTIALS
                 // no break
-            case 50:	// LDAP_INSUFFICIENT_ACCESS
+            case 50: // LDAP_INSUFFICIENT_ACCESS
                 return false;
             default:
                 break;
@@ -485,12 +487,12 @@ class SimpleSAML_Auth_LDAP {
      * @param $value
      * @return void
      */
-    public function setOption($option, $value) {
-
+    public function setOption($option, $value)
+    {
         // Attempt to set the LDAP option
         if (!@ldap_set_option($this->ldap, $option, $value)) {
             throw $this->makeException(
-	        'ldap:LdapConnection->setOption : Failed to set LDAP option [' .
+                'ldap:LdapConnection->setOption : Failed to set LDAP option [' .
                 $option . '] with the value [' . $value . '] error: ' . ldap_error($this->ldap),
                 ERR_INTERNAL
             );
@@ -520,8 +522,8 @@ class SimpleSAML_Auth_LDAP {
      * The array of attributes and their values.
      * @see http://no.php.net/manual/en/function.ldap-read.php
      */
-    public function getAttributes($dn, $attributes = NULL, $maxsize = NULL) {
-
+    public function getAttributes($dn, $attributes = null, $maxsize = null)
+    {
         // Preparations, including a pretty debug message...
         $description = 'all attributes';
         if (is_array($attributes)) {
@@ -597,8 +599,8 @@ class SimpleSAML_Auth_LDAP {
      * @return array|bool
      */
     // TODO: Documentation; only cleared up exception/log messages
-    public function validate($config, $username, $password = null) {
-
+    public function validate($config, $username, $password = null)
+    {
         /* Escape any characters with a special meaning in LDAP. The following
          * characters have a special meaning (according to RFC 2253):
          * ',', '+', '"', '\', '<', '>', ';', '*'
@@ -620,7 +622,7 @@ class SimpleSAML_Auth_LDAP {
             $password = addcslashes($password, ',+"\\<>;*');
             if (!$this->bind($dn, $password)) {
                 SimpleSAML\Logger::info('Library - LDAP validate(): Failed to authenticate \''. $username . '\' using DN \'' . $dn . '\'');
-                return FALSE;
+                return false;
             }
         }
 
@@ -646,7 +648,8 @@ class SimpleSAML_Auth_LDAP {
      * @param array $values Array of values to escape
      * @return array Array $values, but escaped
      */
-    public static function escape_filter_value($values = array(), $singleValue = TRUE) {
+    public static function escape_filter_value($values = array(), $singleValue = true)
+    {
         // Parameter validation
         if (!is_array($values)) {
             $values = array($values);
@@ -685,7 +688,8 @@ class SimpleSAML_Auth_LDAP {
      * @static
      * @return string
      */
-    public static function asc2hex32($string) {
+    public static function asc2hex32($string)
+    {
         for ($i = 0; $i < strlen($string); $i++) {
             $char = substr($string, $i, 1);
             if (ord($char) < 32) {
@@ -702,7 +706,8 @@ class SimpleSAML_Auth_LDAP {
     /**
      * Convert SASL authz_id into a DN
      */
-    private  function authzid_to_dn($searchBase, $searchAttributes, $authz_id) {
+    private function authzid_to_dn($searchBase, $searchAttributes, $authz_id)
+    {
         if (preg_match("/^dn:/", $authz_id)) {
             return preg_replace("/^dn:/", "", $authz_id);
         }
@@ -723,7 +728,8 @@ class SimpleSAML_Auth_LDAP {
      * And the patch against lastest PHP release:
      * http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/databases/php-ldap/files/ldap-ctrl-exop.patch
      */
-    public  function whoami($searchBase, $searchAttributes) {
+    public function whoami($searchBase, $searchAttributes)
+    {
         $authz_id = '';
 
         if (function_exists('ldap_exop_whoami')) {
@@ -742,5 +748,4 @@ class SimpleSAML_Auth_LDAP {
 
         return $dn;
     }
-
 }
diff --git a/modules/ldap/docs/ldap.md b/modules/ldap/docs/ldap.md
index cbc9e6f777e70662cfb8e6a5a703666a3778aa27..098e4042f5cb925551d4edec4b58312de2459b92 100644
--- a/modules/ldap/docs/ldap.md
+++ b/modules/ldap/docs/ldap.md
@@ -462,13 +462,15 @@ a listing of all configuration options and their details.
 		 * that most products have a special query to recursively search
 		 * group membership.
 		 *
-		 * Note: Only ActiveDirectory is currently supported.
+		 * Note: Only ActiveDirectory is currently supported 
+		 * (OpenLDAP is implemented but not supported, see example below).
 		 *
 		 * Default: ''
 		 * Required: No
 		 */
 		'ldap.product' => '',
 		'ldap.product' => 'ActiveDirectory',
+		'ldap.product' => 'OpenLDAP',
 
 
 		/**
@@ -559,3 +561,14 @@ required, see the config info above for details.
 		'ldap.basedn' => 'DC=example,DC=org'
 	)
 
+Example for unsupported OpenLDAP usage. 
+Intention is to filter in 'ou=groups,dc=example,dc=com' for 
+'(memberUid = <UID>)' and take only the attributes 'cn' (=name of the group).
+
+    50 => array(
+        'class' => 'ldap:AttributeAddUsersGroups',
+        'ldap.product' => 'OpenLDAP',
+        'ldap.basedn' => 'ou=groups,dc=example,dc=org',
+        'attribute.member' => 'cn',
+        'attribute.memberof' => 'memberUid',
+    ),
diff --git a/modules/ldap/lib/Auth/Process/AttributeAddFromLDAP.php b/modules/ldap/lib/Auth/Process/AttributeAddFromLDAP.php
index 38c85c0b819f3dae2e11850ddf76a6861028cc3a..b1c5910cb3e77de32295e8cf03b09c628479d7e0 100644
--- a/modules/ldap/lib/Auth/Process/AttributeAddFromLDAP.php
+++ b/modules/ldap/lib/Auth/Process/AttributeAddFromLDAP.php
@@ -29,7 +29,8 @@
  * @author Ryan Panning
  * @package SimpleSAMLphp
  */
-class sspmod_ldap_Auth_Process_AttributeAddFromLDAP extends sspmod_ldap_Auth_Process_BaseFilter {
+class sspmod_ldap_Auth_Process_AttributeAddFromLDAP extends sspmod_ldap_Auth_Process_BaseFilter
+{
 
     /**
      * LDAP attribute to add to the request attributes
@@ -60,8 +61,8 @@ class sspmod_ldap_Auth_Process_AttributeAddFromLDAP extends sspmod_ldap_Auth_Pro
      * @param array $config Configuration information about this filter.
      * @param mixed $reserved For future use.
      */
-    public function __construct($config, $reserved) {
-
+    public function __construct($config, $reserved)
+    {
         /*
          * For backwards compatibility, check for old config names
          * @TODO Remove after 2.0
@@ -119,7 +120,7 @@ class sspmod_ldap_Auth_Process_AttributeAddFromLDAP extends sspmod_ldap_Auth_Pro
             $new_attribute = $this->config->getString('attribute.new', '');
             $this->search_attributes[$new_attribute] = $this->config->getString('search.attribute');
         }
-        $this->search_filter    = $this->config->getString('search.filter');
+        $this->search_filter = $this->config->getString('search.filter');
 
         // get the attribute policy
         $this->attr_policy = $this->config->getString('attribute.policy', 'merge');
@@ -131,7 +132,8 @@ class sspmod_ldap_Auth_Process_AttributeAddFromLDAP extends sspmod_ldap_Auth_Pro
      *
      * @param array &$request The current request
      */
-    public function process(&$request) {
+    public function process(&$request)
+    {
         assert('is_array($request)');
         assert('array_key_exists("Attributes", $request)');
 
@@ -153,7 +155,7 @@ class sspmod_ldap_Auth_Process_AttributeAddFromLDAP extends sspmod_ldap_Auth_Pro
         // merge the attributes into the ldap_search_filter
         $filter = str_replace($arrSearch, $arrReplace, $this->search_filter);
 
-        if (strpos($filter, '%') !== FALSE) {
+        if (strpos($filter, '%') !== false) {
             SimpleSAML\Logger::info('AttributeAddFromLDAP: There are non-existing attributes in the search filter. ('.
                                     $this->search_filter.')');
             return;
@@ -168,7 +170,7 @@ class sspmod_ldap_Auth_Process_AttributeAddFromLDAP extends sspmod_ldap_Auth_Pro
         // search for matching entries
         try {
             $entries = $this->getLdap()->searchformultiple($this->base_dn, $filter,
-                                                           array_values($this->search_attributes), TRUE, FALSE);
+                                                           array_values($this->search_attributes), true, false);
         } catch (Exception $e) {
             return; // silent fail, error is still logged by LDAP search
         }
diff --git a/modules/ldap/lib/Auth/Process/AttributeAddUsersGroups.php b/modules/ldap/lib/Auth/Process/AttributeAddUsersGroups.php
index 6364efe9eddc05952260691b201711964ceb3d9b..ada49327a2cbb170738c5f50882a8bfeb522c081 100644
--- a/modules/ldap/lib/Auth/Process/AttributeAddUsersGroups.php
+++ b/modules/ldap/lib/Auth/Process/AttributeAddUsersGroups.php
@@ -8,287 +8,312 @@
  * @author Ryan Panning <panman@traileyes.com>
  * @package SimpleSAMLphp
  */
-class sspmod_ldap_Auth_Process_AttributeAddUsersGroups extends sspmod_ldap_Auth_Process_BaseFilter {
-
-
-	/**
-	 * This is run when the filter is processed by SimpleSAML.
-	 * It will attempt to find the current users groups using
-	 * the best method possible for the LDAP product. The groups
-	 * are then added to the request attributes.
-	 *
-	 * @throws SimpleSAML_Error_Exception
-	 * @param $request
-	 */
-	public function process(&$request) {
-		assert('is_array($request)');
-		assert('array_key_exists("Attributes", $request)');
-
-		// Log the process
-		SimpleSAML\Logger::debug(
-			$this->title . 'Attempting to get the users groups...'
-		);
-
-		// Reference the attributes, just to make the names shorter
-		$attributes =& $request['Attributes'];
-		$map =& $this->attribute_map;
-
-		// Get the users groups from LDAP
-		$groups = $this->getGroups($attributes);
-
-		// Make the array if it is not set already
-		if (!isset($attributes[$map['groups']])) {
-			$attributes[$map['groups']] = array();
-		}
-
-		// Must be an array, else cannot merge groups
-		if (!is_array($attributes[$map['groups']])) {
-			throw new SimpleSAML_Error_Exception(
-				$this->title . 'The group attribute [' . $map['groups'] .
-				'] is not an array of group DNs. ' . $this->var_export($attributes[$map['groups']])
-			);
-		}
-
-		// Add the users group(s)
-		$group_attribute =& $attributes[$map['groups']];
-		$group_attribute = array_merge($group_attribute, $groups);
-		$group_attribute = array_unique($group_attribute);
-
-		// All done
-		SimpleSAML\Logger::debug(
-			$this->title . 'Added users groups to the group attribute [' .
-			$map['groups'] . ']: ' . implode('; ', $groups)
-		);
-	}
-
-
-	/**
-	 * This section of code was broken out because the child
-	 * filter AuthorizeByGroup can use this method as well.
-	 * Based on the LDAP product, it will do an optimized search
-	 * using the required attribute values from the user to
-	 * get their group membership, recursively.
-	 *
-	 * @throws SimpleSAML_Error_Exception
-	 * @param array $attributes
-	 * @return array
-	 */
-	protected function getGroups(array $attributes) {
-
-		// Reference the map, just to make the name shorter
-		$map =& $this->attribute_map;
-
-		// Log the request
-		SimpleSAML\Logger::debug(
-			$this->title . 'Checking for groups based on the best method for the LDAP product.'
-		);
-
-		// Based on the directory service, search LDAP for groups
-		// If any attributes are needed, prepare them before calling search method
-		switch ($this->product) {
-
-			case 'ACTIVEDIRECTORY':
-
-				// Log the AD specific search
-				SimpleSAML\Logger::debug(
-					$this->title . 'Searching LDAP using ActiveDirectory specific method.'
-				);
-
-				// Make sure the defined dn attribute exists
-				if (!isset($attributes[$map['dn']])) {
-					throw new SimpleSAML_Error_Exception(
-						$this->title . 'The DN attribute [' . $map['dn'] .
-						'] is not defined in the users Attributes: ' . implode(', ', array_keys($attributes))
-					);
-				}
-
-				// DN attribute must have a value
-				if (!isset($attributes[$map['dn']][0]) || !$attributes[$map['dn']][0]) {
-					throw new SimpleSAML_Error_Exception(
-						$this->title . 'The DN attribute [' . $map['dn'] .
-						'] does not have a [0] value defined. ' . $this->var_export($attributes[$map['dn']])
-					);
-				}
-
-				// Pass to the AD specific search
-				$groups = $this->searchActiveDirectory($attributes[$map['dn']][0]);
-				break;
-
-			default:
-
-				// Log the general search
-				SimpleSAML\Logger::debug(
-					$this->title . 'Searching LDAP using the default search method.'
-				);
-
-				// Make sure the defined memberOf attribute exists
-				if (!isset($attributes[$map['memberof']])) {
-					throw new SimpleSAML_Error_Exception(
-						$this->title . 'The memberof attribute [' . $map['memberof'] .
-						'] is not defined in the users Attributes: ' . implode(', ', array_keys($attributes))
-					);
-				}
-
-				// MemberOf must be an array of group DN's
-				if (!is_array($attributes[$map['memberof']])) {
-					throw new SimpleSAML_Error_Exception(
-						$this->title . 'The memberof attribute [' . $map['memberof'] .
-						'] is not an array of group DNs. ' . $this->var_export($attributes[$map['memberof']])
-					);
-				}
-
-				// Search for the users group membership, recursively
-				$groups = $this->search($attributes[$map['memberof']]);
-		}
-
-		// All done
-		SimpleSAML\Logger::debug(
-			$this->title . 'User found to be a member of the groups:' . implode('; ', $groups)
-		);
-		return $groups;
-	}
-
-
-	/**
-	 * Looks for groups from the list of DN's passed. Also
-	 * recursively searches groups for further membership.
-	 * Avoids loops by only searching a DN once. Returns
-	 * the list of groups found.
-	 *
-	 * @param array $memberof
-	 * @return array
-	 */
-	protected function search($memberof) {
-		assert('is_array($memberof)');
-
-		// Used to determine what DN's have already been searched
-		static $searched = array();
-
-		// Init the groups variable
-		$groups = array();
-
-		// Shorten the variable name
-		$map =& $this->attribute_map;
-
-		// Log the search
-		SimpleSAML\Logger::debug(
-			$this->title . 'Checking DNs for groups.' .
-			' DNs: '. implode('; ', $memberof) .
-			' Attributes: ' . $map['memberof'] . ', ' . $map['type'] .
-			' Group Type: ' . $this->type_map['group']
-		);
-
-		// Check each DN of the passed memberOf
-		foreach ($memberof as $dn) {
-
-			// Avoid infinite loops, only need to check a DN once
-			if (isset($searched[$dn])) {
-				continue;
-			}
-
-			// Track all DN's that are searched
-			// Use DN for key as well, isset() is faster than in_array()
-			$searched[$dn] = $dn;
-
-			// Query LDAP for the attribute values for the DN
-			try {
-				$attributes = $this->getLdap()->getAttributes($dn, array($map['memberof'], $map['type']));
-			} catch (SimpleSAML_Error_AuthSource $e) {
-				continue; // DN must not exist, just continue. Logged by the LDAP object
-			}
-
-			// Only look for groups
-			if (!in_array($this->type_map['group'], $attributes[$map['type']])) {
-				continue;
-			}
-
-			// Add to found groups array
-			$groups[] = $dn;
-
-			// Recursively search "sub" groups
-			$groups = array_merge($groups, $this->search($attributes[$map['memberof']]));
-		}
-
-		// Return only the unique group names
-		return array_unique($groups);
-	}
-
-
-	/**
-	 * Searches LDAP using a ActiveDirectory specific filter,
-	 * looking for group membership for the users DN. Returns
-	 * the list of group DNs retrieved.
-	 *
-	 * @param string $dn
-	 * @return array
-	 */
-	protected function searchActiveDirectory($dn) {
-		assert('is_string($dn) && $dn != ""');
-
-		// Shorten the variable name
-		$map =& $this->attribute_map;
-
-		// Log the search
-		SimpleSAML\Logger::debug(
-			$this->title . 'Searching ActiveDirectory group membership.' .
-			' DN: ' . $dn .
-			' DN Attribute: ' . $map['dn'] .
-			' Member Attribute: ' . $map['member'] .
-			' Type Attribute: ' . $map['type'] .
-			' Type Value: ' . $this->type_map['group'] .
-			' Base: ' . implode('; ', $this->base_dn)
-		);
-
-		// AD connections should have this set
-		$this->getLdap()->setOption(LDAP_OPT_REFERRALS, 0);
-
-		// Search AD with the specific recursive flag
-		try {
-			$entries = $this->getLdap()->searchformultiple(
-				$this->base_dn,
-				array($map['type'] => $this->type_map['group'], $map['member'] . ':1.2.840.113556.1.4.1941:' => $dn),
-				array($map['dn'])
-			);
-
-		// The search may throw an exception if no entries
-		// are found, unlikely but possible.
-		} catch (SimpleSAML_Error_UserNotFound $e) {
-			return array();
-		}
-
-		//Init the groups
-		$groups = array();
-
-		// Check each entry..
-		foreach ($entries as $entry) {
-
-			// Check for the DN using the original attribute name
-			if (isset($entry[$map['dn']][0])) {
-				$groups[] = $entry[$map['dn']][0];
-				continue;
-			}
-
-			// Sometimes the returned attribute names are lowercase
-			if (isset($entry[strtolower($map['dn'])][0])) {
-				$groups[] = $entry[strtolower($map['dn'])][0];
-				continue;
-			}
-
-			// AD queries also seem to return the objects dn by default
-			if (isset($entry['dn'])) {
-				$groups[] = $entry['dn'];
-				continue;
-			}
-
-			// Could not find DN, log and continue
-			SimpleSAML\Logger::notice(
-				$this->title . 'The DN attribute [' .
-				implode(', ', array($map['dn'], strtolower($map['dn']), 'dn')) .
-				'] could not be found in the entry. ' . $this->var_export($entry)
-			);
-		}
-
-		// All done
-		return $groups;
-	}
+class sspmod_ldap_Auth_Process_AttributeAddUsersGroups extends sspmod_ldap_Auth_Process_BaseFilter
+{
+    /**
+     * This is run when the filter is processed by SimpleSAML.
+     * It will attempt to find the current users groups using
+     * the best method possible for the LDAP product. The groups
+     * are then added to the request attributes.
+     *
+     * @throws SimpleSAML_Error_Exception
+     * @param $request
+     */
+    public function process(&$request)
+    {
+        assert('is_array($request)');
+        assert('array_key_exists("Attributes", $request)');
+
+        // Log the process
+        SimpleSAML\Logger::debug(
+            $this->title . 'Attempting to get the users groups...'
+        );
+
+        // Reference the attributes, just to make the names shorter
+        $attributes =& $request['Attributes'];
+        $map =& $this->attribute_map;
+
+        // Get the users groups from LDAP
+        $groups = $this->getGroups($attributes);
+
+        // Make the array if it is not set already
+        if (!isset($attributes[$map['groups']])) {
+            $attributes[$map['groups']] = array();
+        }
+
+        // Must be an array, else cannot merge groups
+        if (!is_array($attributes[$map['groups']])) {
+            throw new SimpleSAML_Error_Exception(
+                $this->title . 'The group attribute [' . $map['groups'] .
+                '] is not an array of group DNs. ' . $this->var_export($attributes[$map['groups']])
+            );
+        }
+
+        // Add the users group(s)
+        $group_attribute =& $attributes[$map['groups']];
+        $group_attribute = array_merge($group_attribute, $groups);
+        $group_attribute = array_unique($group_attribute);
+
+        // All done
+        SimpleSAML\Logger::debug(
+            $this->title . 'Added users groups to the group attribute [' .
+            $map['groups'] . ']: ' . implode('; ', $groups)
+        );
+    }
+
+
+    /**
+     * This section of code was broken out because the child
+     * filter AuthorizeByGroup can use this method as well.
+     * Based on the LDAP product, it will do an optimized search
+     * using the required attribute values from the user to
+     * get their group membership, recursively.
+     *
+     * @throws SimpleSAML_Error_Exception
+     * @param array $attributes
+     * @return array
+     */
+    protected function getGroups(array $attributes)
+    {
+        // Reference the map, just to make the name shorter
+        $map =& $this->attribute_map;
+
+        // Log the request
+        SimpleSAML\Logger::debug(
+            $this->title . 'Checking for groups based on the best method for the LDAP product.'
+        );
+
+        // Based on the directory service, search LDAP for groups
+        // If any attributes are needed, prepare them before calling search method
+        switch ($this->product) {
+
+            case 'ACTIVEDIRECTORY':
+
+                // Log the AD specific search
+                SimpleSAML\Logger::debug(
+                    $this->title . 'Searching LDAP using ActiveDirectory specific method.'
+                );
+
+                // Make sure the defined dn attribute exists
+                if (!isset($attributes[$map['dn']])) {
+                    throw new SimpleSAML_Error_Exception(
+                        $this->title . 'The DN attribute [' . $map['dn'] .
+                        '] is not defined in the users Attributes: ' . implode(', ', array_keys($attributes))
+                    );
+                }
+
+                // DN attribute must have a value
+                if (!isset($attributes[$map['dn']][0]) || !$attributes[$map['dn']][0]) {
+                    throw new SimpleSAML_Error_Exception(
+                        $this->title . 'The DN attribute [' . $map['dn'] .
+                        '] does not have a [0] value defined. ' . $this->var_export($attributes[$map['dn']])
+                    );
+                }
+
+                // Pass to the AD specific search
+                $groups = $this->searchActiveDirectory($attributes[$map['dn']][0]);
+                break;
+                
+            case 'OPENLDAP':
+                // Log the OpenLDAP specific search
+                SimpleSAML\Logger::debug(
+                    $this->title . 'Searching LDAP using OpenLDAP specific method.'
+                );
+                // Print group search string and search for all group names
+                $openldap_base = $this->config->getString('ldap.basedn','ou=groups,dc=example,dc=com');
+                SimpleSAML\Logger::debug(
+                    $this->title . "Searching for groups in ldap.basedn ".$openldap_base." with filter (".$map['memberof']."=".$attributes['uid'][0].") and attributes ".$map['member']
+                );
+                $groups = array();
+                try {
+                    // Intention is to filter in 'ou=groups,dc=example,dc=com' for '(memberUid = <UID>)' and take only the attributes 'cn' (=name of the group)
+                    $all_groups = $this->getLdap()->searchformultiple( $openldap_base, array($map['memberof'] => $attributes['uid'][0]) , array($map['member']));
+                } catch (SimpleSAML_Error_UserNotFound $e) {
+                    break; // if no groups found return with empty (still just initialized) groups array
+                }
+                // run through all groups and add each to our groups array
+                foreach ($all_groups as $group_entry) {
+                    $groups[] .= $group_entry[$map['member']][0];
+                }
+                break;
+                                
+            default:
+
+                // Log the general search
+                SimpleSAML\Logger::debug(
+                    $this->title . 'Searching LDAP using the default search method.'
+                );
+
+                // Make sure the defined memberOf attribute exists
+                if (!isset($attributes[$map['memberof']])) {
+                    throw new SimpleSAML_Error_Exception(
+                        $this->title . 'The memberof attribute [' . $map['memberof'] .
+                        '] is not defined in the users Attributes: ' . implode(', ', array_keys($attributes))
+                    );
+                }
+
+                // MemberOf must be an array of group DN's
+                if (!is_array($attributes[$map['memberof']])) {
+                    throw new SimpleSAML_Error_Exception(
+                        $this->title . 'The memberof attribute [' . $map['memberof'] .
+                        '] is not an array of group DNs. ' . $this->var_export($attributes[$map['memberof']])
+                    );
+                }
+
+                // Search for the users group membership, recursively
+                $groups = $this->search($attributes[$map['memberof']]);
+        }
+
+        // All done
+        SimpleSAML\Logger::debug(
+            $this->title . 'User found to be a member of the groups:' . implode('; ', $groups)
+        );
+        return $groups;
+    }
+
+
+    /**
+     * Looks for groups from the list of DN's passed. Also
+     * recursively searches groups for further membership.
+     * Avoids loops by only searching a DN once. Returns
+     * the list of groups found.
+     *
+     * @param array $memberof
+     * @return array
+     */
+    protected function search($memberof)
+    {
+        assert('is_array($memberof)');
+
+        // Used to determine what DN's have already been searched
+        static $searched = array();
+
+        // Init the groups variable
+        $groups = array();
+
+        // Shorten the variable name
+        $map =& $this->attribute_map;
+
+        // Log the search
+        SimpleSAML\Logger::debug(
+            $this->title . 'Checking DNs for groups.' .
+            ' DNs: '. implode('; ', $memberof) .
+            ' Attributes: ' . $map['memberof'] . ', ' . $map['type'] .
+            ' Group Type: ' . $this->type_map['group']
+        );
+
+        // Check each DN of the passed memberOf
+        foreach ($memberof as $dn) {
+
+            // Avoid infinite loops, only need to check a DN once
+            if (isset($searched[$dn])) {
+                continue;
+            }
+
+            // Track all DN's that are searched
+            // Use DN for key as well, isset() is faster than in_array()
+            $searched[$dn] = $dn;
+
+            // Query LDAP for the attribute values for the DN
+            try {
+                $attributes = $this->getLdap()->getAttributes($dn, array($map['memberof'], $map['type']));
+            } catch (SimpleSAML_Error_AuthSource $e) {
+                continue; // DN must not exist, just continue. Logged by the LDAP object
+            }
+
+            // Only look for groups
+            if (!in_array($this->type_map['group'], $attributes[$map['type']])) {
+                continue;
+            }
+
+            // Add to found groups array
+            $groups[] = $dn;
+
+            // Recursively search "sub" groups
+            $groups = array_merge($groups, $this->search($attributes[$map['memberof']]));
+        }
+
+        // Return only the unique group names
+        return array_unique($groups);
+    }
+
+
+    /**
+     * Searches LDAP using a ActiveDirectory specific filter,
+     * looking for group membership for the users DN. Returns
+     * the list of group DNs retrieved.
+     *
+     * @param string $dn
+     * @return array
+     */
+    protected function searchActiveDirectory($dn)
+    {
+        assert('is_string($dn) && $dn != ""');
+
+        // Shorten the variable name
+        $map =& $this->attribute_map;
+
+        // Log the search
+        SimpleSAML\Logger::debug(
+            $this->title . 'Searching ActiveDirectory group membership.' .
+            ' DN: ' . $dn .
+            ' DN Attribute: ' . $map['dn'] .
+            ' Member Attribute: ' . $map['member'] .
+            ' Type Attribute: ' . $map['type'] .
+            ' Type Value: ' . $this->type_map['group'] .
+            ' Base: ' . implode('; ', $this->base_dn)
+        );
+
+        // AD connections should have this set
+        $this->getLdap()->setOption(LDAP_OPT_REFERRALS, 0);
+
+        // Search AD with the specific recursive flag
+        try {
+            $entries = $this->getLdap()->searchformultiple(
+                $this->base_dn,
+                array($map['type'] => $this->type_map['group'], $map['member'] . ':1.2.840.113556.1.4.1941:' => $dn),
+                array($map['dn'])
+            );
+
+        // The search may throw an exception if no entries
+        // are found, unlikely but possible.
+        } catch (SimpleSAML_Error_UserNotFound $e) {
+            return array();
+        }
+
+        //Init the groups
+        $groups = array();
+
+        // Check each entry..
+        foreach ($entries as $entry) {
+
+            // Check for the DN using the original attribute name
+            if (isset($entry[$map['dn']][0])) {
+                $groups[] = $entry[$map['dn']][0];
+                continue;
+            }
+
+            // Sometimes the returned attribute names are lowercase
+            if (isset($entry[strtolower($map['dn'])][0])) {
+                $groups[] = $entry[strtolower($map['dn'])][0];
+                continue;
+            }
+
+            // AD queries also seem to return the objects dn by default
+            if (isset($entry['dn'])) {
+                $groups[] = $entry['dn'];
+                continue;
+            }
+
+            // Could not find DN, log and continue
+            SimpleSAML\Logger::notice(
+                $this->title . 'The DN attribute [' .
+                implode(', ', array($map['dn'], strtolower($map['dn']), 'dn')) .
+                '] could not be found in the entry. ' . $this->var_export($entry)
+            );
+        }
+
+        // All done
+        return $groups;
+    }
 }
diff --git a/modules/ldap/lib/Auth/Process/BaseFilter.php b/modules/ldap/lib/Auth/Process/BaseFilter.php
index 3d328e4481cafe68df03f43a5ba19d121aad8bf6..22aa197bf1bbda1f9348f0d8081543d8520730d8 100644
--- a/modules/ldap/lib/Auth/Process/BaseFilter.php
+++ b/modules/ldap/lib/Auth/Process/BaseFilter.php
@@ -8,270 +8,271 @@
  * @author Ryan Panning <panman@traileyes.com>
  * @package SimpleSAMLphp
  */
-abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_ProcessingFilter {
-
-	/**
-	 * List of attribute "alias's" linked to the real attribute
-	 * name. Used for abstraction / configuration of the LDAP
-	 * attribute names, which may change between dir service.
-	 *
-	 * @var array
-	 */
-	protected $attribute_map;
-
-
-	/**
-	 * The base DN of the LDAP connection. Used when searching
-	 * the LDAP server.
-	 *
-	 * @var string|array
-	 */
-	protected $base_dn;
-
-
-	/**
-	 * The construct method will change the filter config into
-	 * a SimpleSAML_Configuration object and store it here for
-	 * later use, if needed.
-	 *
-	 * @var SimpleSAML_Configuration
-	 */
-	protected $config;
-
-
-	/**
-	 * Instance, object of the ldap connection. Stored here to
-	 * be access later during processing.
-	 *
-	 * @var sspmod_ldap_LdapConnection
-	 */
-	private $ldap;
-
-
-	/**
-	 * Many times a LDAP product specific query can be used to
-	 * speed up or reduce the filter process. This helps the
-	 * child classes determine the product used to optimize
-	 * those queries.
-	 *
-	 * @var string
-	 */
-	protected $product;
-
-
-	/**
-	 * The class "title" used in logging and exception messages.
-	 * This should be prepended to the beginning of the message.
-	 *
-	 * @var string
-	 */
-	protected $title = 'ldap:BaseFilter : ';
-
-
-	/**
-	 * List of LDAP object types, used to determine the type of
-	 * object that a DN references.
-	 *
-	 * @var array
-	 */
-	protected $type_map;
-
-
-	/**
-	 * Checks the authsource, if defined, for configuration values
-	 * to the LDAP server. Then sets up the LDAP connection for the
-	 * instance/object and stores everything in class members.
-	 *
-	 * @throws SimpleSAML_Error_Exception
-	 * @param array $config
-	 * @param $reserved
-	 */
-	public function __construct(&$config, $reserved) {
-		parent::__construct($config, $reserved);
-
-		// Change the class $title to match it's true name
-		// This way if the class is extended the proper name is used
-		$classname = get_class($this);
-		$classname = explode('_', $classname);
-		$this->title = 'ldap:' . end($classname) . ' : ';
-
-		// Log the construction
-		SimpleSAML\Logger::debug(
-			$this->title . 'Creating and configuring the filter.'
-		);
-
-		// If an authsource was defined (an not empty string)...
-		if (isset($config['authsource']) && $config['authsource']) {
-
-			// Log the authsource request
-			SimpleSAML\Logger::debug(
-				$this->title . 'Attempting to get configuration values from authsource [' .
-				$config['authsource'] . ']'
-			);
-
-			// Get the authsources file, which should contain the config
-			$authsource = SimpleSAML_Configuration::getConfig('authsources.php');
-
-			// Verify that the authsource config exists
-			if (!$authsource->hasValue($config['authsource'])) {
-				throw new SimpleSAML_Error_Exception(
-					$this->title . 'Authsource [' . $config['authsource'] .
-					'] defined in filter parameters not found in authsources.php'
-				);
-			}
-
-			// Get just the specified authsource config values
-			$authsource = $authsource->getConfigItem($config['authsource']);
-			$authsource = $authsource->toArray();
-
-			// Make sure it is an ldap source
-			// TODO: Support ldap:LDAPMulti, if possible
-			if (@$authsource[0] != 'ldap:LDAP') {
-				throw new SimpleSAML_Error_Exception(
-					$this->title . 'Authsource [' . $config['authsource'] .
-					'] specified in filter parameters is not an ldap:LDAP type'
-				);
-			}
-
-			// Build the authsource config
-			$authconfig = array();
-			$authconfig['ldap.hostname']   = @$authsource['hostname'];
-			$authconfig['ldap.enable_tls'] = @$authsource['enable_tls'];
-			$authconfig['ldap.port']       = @$authsource['port'];
-			$authconfig['ldap.timeout']    = @$authsource['timeout'];
-			$authconfig['ldap.debug']      = @$authsource['debug'];
-			$authconfig['ldap.basedn']     = (@$authsource['search.enable'] ? @$authsource['search.base'] : NULL);
-			$authconfig['ldap.username']   = (@$authsource['search.enable'] ? @$authsource['search.username'] : NULL);
-			$authconfig['ldap.password']   = (@$authsource['search.enable'] ? @$authsource['search.password'] : NULL);
-			$authconfig['ldap.username']   = (@$authsource['priv.read'] ? @$authsource['priv.username'] : $authconfig['ldap.username']);
-			$authconfig['ldap.password']   = (@$authsource['priv.read'] ? @$authsource['priv.password'] : $authconfig['ldap.password']);
-
-			// Only set the username attribute if the authsource specifies one attribute
-			if (@$authsource['search.enable'] && is_array(@$authsource['search.attributes'])
-			     && count($authsource['search.attributes']) == 1) {
-				$authconfig['attribute.username'] = reset($authsource['search.attributes']);
-			}
-
-			// Merge the authsource config with the filter config,
-			// but have the filter config override the authsource config
-			$config = array_merge($authconfig, $config);
-
-			// Authsource complete
-			SimpleSAML\Logger::debug(
-				$this->title . 'Retrieved authsource [' . $config['authsource'] .
-				'] configuration values: ' . $this->var_export($authconfig)
-			);
-		}
-
-		// Convert the config array to a config class,
-		// that way we can verify type and define defaults.
-		// Store in the instance in-case needed later, by a child class.
-		$this->config = SimpleSAML_Configuration::loadFromArray($config, 'ldap:AuthProcess');
-
-		// Set all the filter values, setting defaults if needed
-		$this->base_dn = $this->config->getArrayizeString('ldap.basedn', '');
-		$this->product = $this->config->getString('ldap.product', '');
-
-		// Cleanup the directory service, so that it is easier for
-		// child classes to determine service name consistently
-		$this->product = trim($this->product);
-		$this->product = strtoupper($this->product);
-
-		// Log the member values retrieved above
-		SimpleSAML\Logger::debug(
-			$this->title . 'Configuration values retrieved;' .
-			' BaseDN: ' . $this->var_export($this->base_dn) .
-			' Product: ' . $this->var_export($this->product)
-		);
-
-		// Setup the attribute map which will be used to search LDAP
-		$this->attribute_map = array(
-			'dn'       => $this->config->getString('attribute.dn', 'distinguishedName'),
-			'groups'   => $this->config->getString('attribute.groups', 'groups'),
-			'member'   => $this->config->getString('attribute.member', 'member'),
-			'memberof' => $this->config->getString('attribute.memberof', 'memberOf'),
-			'name'     => $this->config->getString('attribute.groupname', 'name'),
-			'type'     => $this->config->getString('attribute.type', 'objectClass'),
-			'username' => $this->config->getString('attribute.username', 'sAMAccountName')
-		);
-
-		// Log the attribute map
-		SimpleSAML\Logger::debug(
-			$this->title . 'Attribute map created: ' . $this->var_export($this->attribute_map)
-		);
-
-		// Setup the object type map which is used to determine a DNs' type
-		$this->type_map = array(
-			'group' => $this->config->getString('type.group', 'group'),
-			'user'  => $this->config->getString('type.user', 'user')
-		);
-
-		// Log the type map
-		SimpleSAML\Logger::debug(
-			$this->title . 'Type map created: ' . $this->var_export($this->type_map)
-		);
-	}
-
-
-	/**
-	 * Getter for the LDAP connection object. Created this getter
-	 * rather than setting in the constructor to avoid unnecessarily
-	 * connecting to LDAP when it might not be needed.
-	 *
-	 * @return sspmod_ldap_LdapConnection
-	 */
-	protected function getLdap() {
-
-		// Check if already connected
-		if ($this->ldap) {
-			return $this->ldap;
-		}
-
-		// Get the connection specific options
-		$hostname   = $this->config->getString('ldap.hostname');
-		$port       = $this->config->getInteger('ldap.port', 389);
-		$enable_tls = $this->config->getBoolean('ldap.enable_tls', FALSE);
-		$debug      = $this->config->getBoolean('ldap.debug', FALSE);
-		$timeout    = $this->config->getInteger('ldap.timeout', 0);
-		$username   = $this->config->getString('ldap.username', NULL);
-		$password   = $this->config->getString('ldap.password', NULL);
-
-		// Log the LDAP connection
-		SimpleSAML\Logger::debug(
-			$this->title . 'Connecting to LDAP server;' .
-			' Hostname: ' . $hostname .
-			' Port: ' . $port .
-			' Enable TLS: ' . ($enable_tls ? 'Yes' : 'No') .
-			' Debug: ' . ($debug ? 'Yes' : 'No') .
-			' Timeout: ' . $timeout .
-			' Username: ' . $username .
-			' Password: ' . str_repeat('*', strlen($password))
-		);
-
-		// Connect to the LDAP server to be queried during processing
-		$this->ldap = new SimpleSAML_Auth_LDAP($hostname, $enable_tls, $debug, $timeout, $port);
-		$this->ldap->bind($username, $password);
-
-		// All done
-		return $this->ldap;
-	}
-
-
-	/**
-	 * Local utility function to get details about a variable,
-	 * basically converting it to a string to be used in a log
-	 * message. The var_export() function returns several lines
-	 * so this will remove the new lines and trim each line.
-	 *
-	 * @param mixed $value
-	 * @return string
-	 */
-	protected function var_export($value) {
-		$export = var_export($value, TRUE);
-		$lines = explode("\n", $export);
-		foreach ($lines as &$line) {
-			$line = trim($line);
-		}
-		return implode(' ', $lines);
-	}
+abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_ProcessingFilter
+{
+
+    /**
+     * List of attribute "alias's" linked to the real attribute
+     * name. Used for abstraction / configuration of the LDAP
+     * attribute names, which may change between dir service.
+     *
+     * @var array
+     */
+    protected $attribute_map;
+
+
+    /**
+     * The base DN of the LDAP connection. Used when searching
+     * the LDAP server.
+     *
+     * @var string|array
+     */
+    protected $base_dn;
+
+
+    /**
+     * The construct method will change the filter config into
+     * a SimpleSAML_Configuration object and store it here for
+     * later use, if needed.
+     *
+     * @var SimpleSAML_Configuration
+     */
+    protected $config;
+
+
+    /**
+     * Instance, object of the ldap connection. Stored here to
+     * be access later during processing.
+     *
+     * @var sspmod_ldap_LdapConnection
+     */
+    private $ldap;
+
+
+    /**
+     * Many times a LDAP product specific query can be used to
+     * speed up or reduce the filter process. This helps the
+     * child classes determine the product used to optimize
+     * those queries.
+     *
+     * @var string
+     */
+    protected $product;
+
+
+    /**
+     * The class "title" used in logging and exception messages.
+     * This should be prepended to the beginning of the message.
+     *
+     * @var string
+     */
+    protected $title = 'ldap:BaseFilter : ';
+
+
+    /**
+     * List of LDAP object types, used to determine the type of
+     * object that a DN references.
+     *
+     * @var array
+     */
+    protected $type_map;
+
+
+    /**
+     * Checks the authsource, if defined, for configuration values
+     * to the LDAP server. Then sets up the LDAP connection for the
+     * instance/object and stores everything in class members.
+     *
+     * @throws SimpleSAML_Error_Exception
+     * @param array $config
+     * @param $reserved
+     */
+    public function __construct(&$config, $reserved)
+    {
+        parent::__construct($config, $reserved);
+
+        // Change the class $title to match it's true name
+        // This way if the class is extended the proper name is used
+        $classname = get_class($this);
+        $classname = explode('_', $classname);
+        $this->title = 'ldap:' . end($classname) . ' : ';
+
+        // Log the construction
+        SimpleSAML\Logger::debug(
+            $this->title . 'Creating and configuring the filter.'
+        );
+
+        // If an authsource was defined (an not empty string)...
+        if (isset($config['authsource']) && $config['authsource']) {
+
+            // Log the authsource request
+            SimpleSAML\Logger::debug(
+                $this->title . 'Attempting to get configuration values from authsource [' .
+                $config['authsource'] . ']'
+            );
+
+            // Get the authsources file, which should contain the config
+            $authsource = SimpleSAML_Configuration::getConfig('authsources.php');
+
+            // Verify that the authsource config exists
+            if (!$authsource->hasValue($config['authsource'])) {
+                throw new SimpleSAML_Error_Exception(
+                    $this->title . 'Authsource [' . $config['authsource'] .
+                    '] defined in filter parameters not found in authsources.php'
+                );
+            }
+
+            // Get just the specified authsource config values
+            $authsource = $authsource->getConfigItem($config['authsource']);
+            $authsource = $authsource->toArray();
+
+            // Make sure it is an ldap source
+            // TODO: Support ldap:LDAPMulti, if possible
+            if (@$authsource[0] != 'ldap:LDAP') {
+                throw new SimpleSAML_Error_Exception(
+                    $this->title . 'Authsource [' . $config['authsource'] .
+                    '] specified in filter parameters is not an ldap:LDAP type'
+                );
+            }
+
+            // Build the authsource config
+            $authconfig = array();
+            $authconfig['ldap.hostname']   = @$authsource['hostname'];
+            $authconfig['ldap.enable_tls'] = @$authsource['enable_tls'];
+            $authconfig['ldap.port']       = @$authsource['port'];
+            $authconfig['ldap.timeout']    = @$authsource['timeout'];
+            $authconfig['ldap.debug']      = @$authsource['debug'];
+            $authconfig['ldap.basedn']     = (@$authsource['search.enable'] ? @$authsource['search.base'] : null);
+            $authconfig['ldap.username']   = (@$authsource['search.enable'] ? @$authsource['search.username'] : null);
+            $authconfig['ldap.password']   = (@$authsource['search.enable'] ? @$authsource['search.password'] : null);
+            $authconfig['ldap.username']   = (@$authsource['priv.read'] ? @$authsource['priv.username'] : $authconfig['ldap.username']);
+            $authconfig['ldap.password']   = (@$authsource['priv.read'] ? @$authsource['priv.password'] : $authconfig['ldap.password']);
+
+            // Only set the username attribute if the authsource specifies one attribute
+            if (@$authsource['search.enable'] && is_array(@$authsource['search.attributes'])
+                 && count($authsource['search.attributes']) == 1) {
+                $authconfig['attribute.username'] = reset($authsource['search.attributes']);
+            }
+
+            // Merge the authsource config with the filter config,
+            // but have the filter config override the authsource config
+            $config = array_merge($authconfig, $config);
+
+            // Authsource complete
+            SimpleSAML\Logger::debug(
+                $this->title . 'Retrieved authsource [' . $config['authsource'] .
+                '] configuration values: ' . $this->var_export($authconfig)
+            );
+        }
+
+        // Convert the config array to a config class,
+        // that way we can verify type and define defaults.
+        // Store in the instance in-case needed later, by a child class.
+        $this->config = SimpleSAML_Configuration::loadFromArray($config, 'ldap:AuthProcess');
+
+        // Set all the filter values, setting defaults if needed
+        $this->base_dn = $this->config->getArrayizeString('ldap.basedn', '');
+        $this->product = $this->config->getString('ldap.product', '');
+
+        // Cleanup the directory service, so that it is easier for
+        // child classes to determine service name consistently
+        $this->product = trim($this->product);
+        $this->product = strtoupper($this->product);
+
+        // Log the member values retrieved above
+        SimpleSAML\Logger::debug(
+            $this->title . 'Configuration values retrieved;' .
+            ' BaseDN: ' . $this->var_export($this->base_dn) .
+            ' Product: ' . $this->var_export($this->product)
+        );
+
+        // Setup the attribute map which will be used to search LDAP
+        $this->attribute_map = array(
+            'dn'       => $this->config->getString('attribute.dn', 'distinguishedName'),
+            'groups'   => $this->config->getString('attribute.groups', 'groups'),
+            'member'   => $this->config->getString('attribute.member', 'member'),
+            'memberof' => $this->config->getString('attribute.memberof', 'memberOf'),
+            'name'     => $this->config->getString('attribute.groupname', 'name'),
+            'type'     => $this->config->getString('attribute.type', 'objectClass'),
+            'username' => $this->config->getString('attribute.username', 'sAMAccountName')
+        );
+
+        // Log the attribute map
+        SimpleSAML\Logger::debug(
+            $this->title . 'Attribute map created: ' . $this->var_export($this->attribute_map)
+        );
+
+        // Setup the object type map which is used to determine a DNs' type
+        $this->type_map = array(
+            'group' => $this->config->getString('type.group', 'group'),
+            'user'  => $this->config->getString('type.user', 'user')
+        );
+
+        // Log the type map
+        SimpleSAML\Logger::debug(
+            $this->title . 'Type map created: ' . $this->var_export($this->type_map)
+        );
+    }
+
+    /**
+     * Getter for the LDAP connection object. Created this getter
+     * rather than setting in the constructor to avoid unnecessarily
+     * connecting to LDAP when it might not be needed.
+     *
+     * @return sspmod_ldap_LdapConnection
+     */
+    protected function getLdap()
+    {
+        // Check if already connected
+        if ($this->ldap) {
+            return $this->ldap;
+        }
+
+        // Get the connection specific options
+        $hostname   = $this->config->getString('ldap.hostname');
+        $port       = $this->config->getInteger('ldap.port', 389);
+        $enable_tls = $this->config->getBoolean('ldap.enable_tls', false);
+        $debug      = $this->config->getBoolean('ldap.debug', false);
+        $timeout    = $this->config->getInteger('ldap.timeout', 0);
+        $username   = $this->config->getString('ldap.username', null);
+        $password   = $this->config->getString('ldap.password', null);
+
+        // Log the LDAP connection
+        SimpleSAML\Logger::debug(
+            $this->title . 'Connecting to LDAP server;' .
+            ' Hostname: ' . $hostname .
+            ' Port: ' . $port .
+            ' Enable TLS: ' . ($enable_tls ? 'Yes' : 'No') .
+            ' Debug: ' . ($debug ? 'Yes' : 'No') .
+            ' Timeout: ' . $timeout .
+            ' Username: ' . $username .
+            ' Password: ' . str_repeat('*', strlen($password))
+        );
+
+        // Connect to the LDAP server to be queried during processing
+        $this->ldap = new SimpleSAML_Auth_LDAP($hostname, $enable_tls, $debug, $timeout, $port);
+        $this->ldap->bind($username, $password);
+
+        // All done
+        return $this->ldap;
+    }
+
+    /**
+     * Local utility function to get details about a variable,
+     * basically converting it to a string to be used in a log
+     * message. The var_export() function returns several lines
+     * so this will remove the new lines and trim each line.
+     *
+     * @param mixed $value
+     * @return string
+     */
+    protected function var_export($value)
+    {
+        $export = var_export($value, true);
+        $lines = explode("\n", $export);
+        foreach ($lines as &$line) {
+            $line = trim($line);
+        }
+        return implode(' ', $lines);
+    }
 }
diff --git a/modules/ldap/lib/Auth/Source/LDAP.php b/modules/ldap/lib/Auth/Source/LDAP.php
index 83b35faf930bd6f9648cbe1e4b16cfdc6caedf40..7bf979a123fb85c6d80342fca32560c9dafdce39 100644
--- a/modules/ldap/lib/Auth/Source/LDAP.php
+++ b/modules/ldap/lib/Auth/Source/LDAP.php
@@ -10,45 +10,48 @@
  *
  * @package SimpleSAMLphp
  */
-class sspmod_ldap_Auth_Source_LDAP extends sspmod_core_Auth_UserPassBase {
-
-	/**
-	 * A LDAP configuration object.
-	 */
-	private $ldapConfig;
-
-
-	/**
-	 * Constructor for this authentication source.
-	 *
-	 * @param array $info  Information about this authentication source.
-	 * @param array $config  Configuration.
-	 */
-	public function __construct($info, $config) {
-		assert('is_array($info)');
-		assert('is_array($config)');
-
-		// Call the parent constructor first, as required by the interface
-		parent::__construct($info, $config);
-
-		$this->ldapConfig = new sspmod_ldap_ConfigHelper($config,
-			'Authentication source ' . var_export($this->authId, TRUE));
-	}
-
-
-	/**
-	 * Attempt to log in using the given username and password.
-	 *
-	 * @param string $username  The username the user wrote.
-	 * @param string $password  The password the user wrote.
-	 * param array $sasl_arg  Associative array of SASL options
-	 * @return array  Associative array with the users attributes.
-	 */
-	protected function login($username, $password, array $sasl_args = NULL) {
-		assert('is_string($username)');
-		assert('is_string($password)');
-
-		return $this->ldapConfig->login($username, $password, $sasl_args);
-	}
+class sspmod_ldap_Auth_Source_LDAP extends sspmod_core_Auth_UserPassBase
+{
+
+    /**
+     * A LDAP configuration object.
+     */
+    private $ldapConfig;
+
+
+    /**
+     * Constructor for this authentication source.
+     *
+     * @param array $info  Information about this authentication source.
+     * @param array $config  Configuration.
+     */
+    public function __construct($info, $config)
+    {
+        assert('is_array($info)');
+        assert('is_array($config)');
+
+        // Call the parent constructor first, as required by the interface
+        parent::__construct($info, $config);
+
+        $this->ldapConfig = new sspmod_ldap_ConfigHelper($config,
+            'Authentication source ' . var_export($this->authId, true));
+    }
+
+
+    /**
+     * Attempt to log in using the given username and password.
+     *
+     * @param string $username  The username the user wrote.
+     * @param string $password  The password the user wrote.
+     * param array $sasl_arg  Associative array of SASL options
+     * @return array  Associative array with the users attributes.
+     */
+    protected function login($username, $password, array $sasl_args = null)
+    {
+        assert('is_string($username)');
+        assert('is_string($password)');
+
+        return $this->ldapConfig->login($username, $password, $sasl_args);
+    }
 
 }
diff --git a/modules/ldap/lib/Auth/Source/LDAPMulti.php b/modules/ldap/lib/Auth/Source/LDAPMulti.php
index 4f5adaf5a280695cd07040c4da5eecf45f0df4ae..e38118efacd8a2a2e1c968c9932e02e8e8a343be 100644
--- a/modules/ldap/lib/Auth/Source/LDAPMulti.php
+++ b/modules/ldap/lib/Auth/Source/LDAPMulti.php
@@ -10,112 +10,115 @@
  *
  * @package SimpleSAMLphp
  */
-class sspmod_ldap_Auth_Source_LDAPMulti extends sspmod_core_Auth_UserPassOrgBase {
-
-	/**
-	 * An array with descriptions for organizations.
-	 */
-	private $orgs;
-
-	/**
-	 * An array of organization IDs to LDAP configuration objects.
-	 */
-	private $ldapOrgs;
-
-	/**
-	 * Whether we should include the organization as part of the username.
-	 */
-	private $includeOrgInUsername;
-
-
-	/**
-	 * Constructor for this authentication source.
-	 *
-	 * @param array $info  Information about this authentication source.
-	 * @param array $config  Configuration.
-	 */
-	public function __construct($info, $config) {
-		assert('is_array($info)');
-		assert('is_array($config)');
-
-		// Call the parent constructor first, as required by the interface
-		parent::__construct($info, $config);
-
-		$cfgHelper = SimpleSAML_Configuration::loadFromArray($config,
-			'Authentication source ' . var_export($this->authId, TRUE));
-
-
-		$this->orgs = array();
-		$this->ldapOrgs = array();
-		foreach ($config as $name => $value) {
-
-			if ($name === 'username_organization_method') {
-				$usernameOrgMethod = $cfgHelper->getValueValidate(
-					'username_organization_method',
-					array('none', 'allow', 'force'));
-				$this->setUsernameOrgMethod($usernameOrgMethod);
-				continue;
-			}
-
-			if ($name === 'include_organization_in_username') {
-				$this->includeOrgInUsername = $cfgHelper->getBoolean(
-					'include_organization_in_username', FALSE);
-				continue;
-			}
-
-			$orgCfg = $cfgHelper->getArray($name);
-			$orgId = $name;
-
-			if (array_key_exists('description', $orgCfg)) {
-				$this->orgs[$orgId] = $orgCfg['description'];
-			} else {
-				$this->orgs[$orgId] = $orgId;
-			}
-
-			$orgCfg = new sspmod_ldap_ConfigHelper($orgCfg,
-				'Authentication source ' . var_export($this->authId, TRUE) .
-				', organization ' . var_export($orgId, TRUE));
-			$this->ldapOrgs[$orgId] = $orgCfg;
-		}
-	}
-
-
-	/**
-	 * Attempt to log in using the given username and password.
-	 *
-	 * @param string $username  The username the user wrote.
-	 * @param string $password  The password the user wrote.
-	 * @param string $org  The organization the user chose.
-	 * @return array  Associative array with the users attributes.
-	 */
-	protected function login($username, $password, $org, array $sasl_args = NULL) {
-		assert('is_string($username)');
-		assert('is_string($password)');
-		assert('is_string($org)');
-
-		if (!array_key_exists($org, $this->ldapOrgs)) {
-			// The user has selected an organization which doesn't exist anymore.
-			SimpleSAML\Logger::warning('Authentication source ' . var_export($this->authId, TRUE) .
-				': Organization seems to have disappeared while the user logged in.' .
-				' Organization was ' . var_export($org, TRUE));
-			throw new SimpleSAML_Error_Error('WRONGUSERPASS');
-		}
-
-		if ($this->includeOrgInUsername) {
-			$username = $username . '@' . $org;
-		}
-
-		return $this->ldapOrgs[$org]->login($username, $password, $sasl_args);
-	}
-
-
-	/**
-	 * Retrieve list of organizations.
-	 *
-	 * @return array  Associative array with the organizations.
-	 */
-	protected function getOrganizations() {
-		return $this->orgs;
-	}
-
+class sspmod_ldap_Auth_Source_LDAPMulti extends sspmod_core_Auth_UserPassOrgBase
+{
+
+    /**
+     * An array with descriptions for organizations.
+     */
+    private $orgs;
+
+    /**
+     * An array of organization IDs to LDAP configuration objects.
+     */
+    private $ldapOrgs;
+
+    /**
+     * Whether we should include the organization as part of the username.
+     */
+    private $includeOrgInUsername;
+
+
+    /**
+     * Constructor for this authentication source.
+     *
+     * @param array $info  Information about this authentication source.
+     * @param array $config  Configuration.
+     */
+    public function __construct($info, $config)
+    {
+        assert('is_array($info)');
+        assert('is_array($config)');
+
+        // Call the parent constructor first, as required by the interface
+        parent::__construct($info, $config);
+
+        $cfgHelper = SimpleSAML_Configuration::loadFromArray($config,
+            'Authentication source ' . var_export($this->authId, true));
+
+
+        $this->orgs = array();
+        $this->ldapOrgs = array();
+        foreach ($config as $name => $value) {
+
+            if ($name === 'username_organization_method') {
+                $usernameOrgMethod = $cfgHelper->getValueValidate(
+                    'username_organization_method',
+                    array('none', 'allow', 'force'));
+                $this->setUsernameOrgMethod($usernameOrgMethod);
+                continue;
+            }
+
+            if ($name === 'include_organization_in_username') {
+                $this->includeOrgInUsername = $cfgHelper->getBoolean(
+                    'include_organization_in_username', false);
+                continue;
+            }
+
+            $orgCfg = $cfgHelper->getArray($name);
+            $orgId = $name;
+
+            if (array_key_exists('description', $orgCfg)) {
+                $this->orgs[$orgId] = $orgCfg['description'];
+            } else {
+                $this->orgs[$orgId] = $orgId;
+            }
+
+            $orgCfg = new sspmod_ldap_ConfigHelper($orgCfg,
+                'Authentication source ' . var_export($this->authId, true) .
+                ', organization ' . var_export($orgId, true));
+            $this->ldapOrgs[$orgId] = $orgCfg;
+        }
+    }
+
+
+    /**
+     * Attempt to log in using the given username and password.
+     *
+     * @param string $username  The username the user wrote.
+     * @param string $password  The password the user wrote.
+     * @param string $org  The organization the user chose.
+     * @return array  Associative array with the users attributes.
+     */
+    protected function login($username, $password, $org, array $sasl_args = null)
+    {
+        assert('is_string($username)');
+        assert('is_string($password)');
+        assert('is_string($org)');
+
+        if (!array_key_exists($org, $this->ldapOrgs)) {
+            // The user has selected an organization which doesn't exist anymore.
+            SimpleSAML\Logger::warning('Authentication source ' . var_export($this->authId, true) .
+                ': Organization seems to have disappeared while the user logged in.' .
+                ' Organization was ' . var_export($org, true));
+            throw new SimpleSAML_Error_Error('WRONGUSERPASS');
+        }
+
+        if ($this->includeOrgInUsername) {
+            $username = $username . '@' . $org;
+        }
+
+        return $this->ldapOrgs[$org]->login($username, $password, $sasl_args);
+    }
+
+
+    /**
+     * Retrieve list of organizations.
+     *
+     * @return array  Associative array with the organizations.
+     */
+    protected function getOrganizations()
+    {
+        return $this->orgs;
+    }
 }
diff --git a/modules/ldap/lib/ConfigHelper.php b/modules/ldap/lib/ConfigHelper.php
index 7c8802db8acb09f0247a1adba97e67a69bd65d1b..28e4151eefa55e9cd44998c1069b5908c8bdccd6 100644
--- a/modules/ldap/lib/ConfigHelper.php
+++ b/modules/ldap/lib/ConfigHelper.php
@@ -8,292 +8,297 @@
  *
  * @package SimpleSAMLphp
  */
-class sspmod_ldap_ConfigHelper {
+class sspmod_ldap_ConfigHelper
+{
+    /**
+     * String with the location of this configuration.
+     * Used for error reporting.
+     */
+    private $location;
 
 
-	/**
-	 * String with the location of this configuration.
-	 * Used for error reporting.
-	 */
-	private $location;
+    /**
+     * The hostname of the LDAP server.
+     */
+    private $hostname;
 
 
-	/**
-	 * The hostname of the LDAP server.
-	 */
-	private $hostname;
+    /**
+     * Whether we should use TLS/SSL when contacting the LDAP server.
+     */
+    private $enableTLS;
 
 
-	/**
-	 * Whether we should use TLS/SSL when contacting the LDAP server.
-	 */
-	private $enableTLS;
+    /**
+     * Whether debug output is enabled.
+     *
+     * @var bool
+     */
+    private $debug;
 
 
-	/**
-	 * Whether debug output is enabled.
-	 *
-	 * @var bool
-	 */
-	private $debug;
+    /**
+     * The timeout for accessing the LDAP server.
+     *
+     * @var int
+     */
+    private $timeout;
 
+    /**
+     * The port used when accessing the LDAP server.
+     *
+     * @var int
+     */
+    private $port;
 
-	/**
-	 * The timeout for accessing the LDAP server.
-	 *
-	 * @var int
-	 */
-	private $timeout;
+    /**
+     * Whether to follow referrals
+     */
+    private $referrals;
 
-	/**
-	 * The port used when accessing the LDAP server.
-	 *
-	 * @var int
-	 */
-	private $port;
 
-	/**
-	 * Whether to follow referrals
-	 */
-	private $referrals;
+    /**
+     * Whether we need to search for the users DN.
+     */
+    private $searchEnable;
 
 
-	/**
-	 * Whether we need to search for the users DN.
-	 */
-	private $searchEnable;
+    /**
+     * The username we should bind with before we can search for the user.
+     */
+    private $searchUsername;
 
 
-	/**
-	 * The username we should bind with before we can search for the user.
-	 */
-	private $searchUsername;
+    /**
+     * The password we should bind with before we can search for the user.
+     */
+    private $searchPassword;
 
 
-	/**
-	 * The password we should bind with before we can search for the user.
-	 */
-	private $searchPassword;
-
-
-	/**
-	 * Array with the base DN(s) for the search.
-	 */
-	private $searchBase;
-
-	/**
-	 * Additional LDAP filter fields for the search
-	 */
-	private $searchFilter;
-
-	/**
-	 * The attributes which should match the username.
-	 */
-	private $searchAttributes;
-
-
-	/**
-	 * The DN pattern we should use to create the DN from the username.
-	 */
-	private $dnPattern;
-
-
-	/**
-	 * The attributes we should fetch. Can be NULL in which case we will fetch all attributes.
-	 */
-	private $attributes;
-
-
-	/**
-	 * The user cannot get all attributes, privileged reader required
-	 */
-	private $privRead;
-
-
-	/**
-	 * The DN we should bind with before we can get the attributes.
-	 */
-	private $privUsername;
-
-
-	/**
-	 * The password we should bind with before we can get the attributes.
-	 */
-	private $privPassword;
-
-
-	/**
-	 * Constructor for this configuration parser.
-	 *
-	 * @param array $config  Configuration.
-	 * @param string $location  The location of this configuration. Used for error reporting.
-	 */
-	public function __construct($config, $location) {
-		assert('is_array($config)');
-		assert('is_string($location)');
-
-		$this->location = $location;
-
-		// Parse configuration
-		$config = SimpleSAML_Configuration::loadFromArray($config, $location);
-
-		$this->hostname = $config->getString('hostname');
-		$this->enableTLS = $config->getBoolean('enable_tls', FALSE);
-		$this->debug = $config->getBoolean('debug', FALSE);
-		$this->timeout = $config->getInteger('timeout', 0);
-		$this->port = $config->getInteger('port', 389);
-		$this->referrals = $config->getBoolean('referrals', TRUE);
-		$this->searchEnable = $config->getBoolean('search.enable', FALSE);
-		$this->privRead = $config->getBoolean('priv.read', FALSE);
-
-		if ($this->searchEnable) {
-			$this->searchUsername = $config->getString('search.username', NULL);
-			if ($this->searchUsername !== NULL) {
-				$this->searchPassword = $config->getString('search.password');
-			}
-
-			$this->searchBase = $config->getArrayizeString('search.base');
-			$this->searchFilter = $config->getString('search.filter',NULL);
-			$this->searchAttributes = $config->getArray('search.attributes');
-
-		} else {
-			$this->dnPattern = $config->getString('dnpattern');
-		}
-
-		// Are privs needed to get to the attributes?
-		if ($this->privRead) {
-			$this->privUsername = $config->getString('priv.username');
-			$this->privPassword = $config->getString('priv.password');
-		}
-
-		$this->attributes = $config->getArray('attributes', NULL);
-	}
-
-
-	/**
-	 * Attempt to log in using the given username and password.
-	 *
-	 * Will throw a SimpleSAML_Error_Error('WRONGUSERPASS') if the username or password is wrong.
-	 * If there is a configuration problem, an Exception will be thrown.
-	 *
-	 * @param string $username  The username the user wrote.
-	 * @param string $password  The password the user wrote.
-	 * @param arrray $sasl_args  Array of SASL options for LDAP bind.
-	 * @return array  Associative array with the users attributes.
-	 */
-	public function login($username, $password, array $sasl_args = NULL) {
-		assert('is_string($username)');
-		assert('is_string($password)');
-
-		if (empty($password)) {
-			SimpleSAML\Logger::info($this->location . ': Login with empty password disallowed.');
-			throw new SimpleSAML_Error_Error('WRONGUSERPASS');
-		}
-
-		$ldap = new SimpleSAML_Auth_LDAP($this->hostname, $this->enableTLS, $this->debug, $this->timeout, $this->port, $this->referrals);
-
-		if (!$this->searchEnable) {
-			$ldapusername = addcslashes($username, ',+"\\<>;*');
-			$dn = str_replace('%username%', $ldapusername, $this->dnPattern);
-		} else {
-			if ($this->searchUsername !== NULL) {
-				if(!$ldap->bind($this->searchUsername, $this->searchPassword)) {
-					throw new Exception('Error authenticating using search username & password.');
-				}
-			}
-
-			$dn = $ldap->searchfordn($this->searchBase, $this->searchAttributes, $username, TRUE, $this->searchFilter);
-			if ($dn === NULL) {
-				/* User not found with search. */
-				SimpleSAML\Logger::info($this->location . ': Unable to find users DN. username=\'' . $username . '\'');
-				throw new SimpleSAML_Error_Error('WRONGUSERPASS');
-			}
-		}
-
-		if (!$ldap->bind($dn, $password, $sasl_args)) {
-			SimpleSAML\Logger::info($this->location . ': '. $username . ' failed to authenticate. DN=' . $dn);
-			throw new SimpleSAML_Error_Error('WRONGUSERPASS');
-		}
-
-		/* In case of SASL bind, authenticated and authorized DN may differ */
-		if (isset($sasl_args))
-			$dn = $ldap->whoami($this->searchBase, $this->searchAttributes);
-
-		/* Are privs needed to get the attributes? */
-		if ($this->privRead) {
-			/* Yes, rebind with privs */
-			if(!$ldap->bind($this->privUsername, $this->privPassword)) {
-				throw new Exception('Error authenticating using privileged DN & password.');
-			}
-		}
-
-		return $ldap->getAttributes($dn, $this->attributes);
-	}
-
-
-	/**
-	 * Search for a DN.
-	 *
-	 * @param string|array $attribute
-	 * The attribute name(s) searched for. If set to NULL, values from
-	 * configuration is used.
-	 * @param string $value
-	 * The attribute value searched for.
-	 * @param bool $allowZeroHits
-	 * Determines if the method will throw an exception if no
-	 * hits are found. Defaults to FALSE.
-	 * @return string
-	 * The DN of the matching element, if found. If no element was
-	 * found and $allowZeroHits is set to FALSE, an exception will
-	 * be thrown; otherwise NULL will be returned.
-	 * @throws SimpleSAML_Error_AuthSource if:
-	 * - LDAP search encounter some problems when searching cataloge
-	 * - Not able to connect to LDAP server
-	 * @throws SimpleSAML_Error_UserNotFound if:
-	 * - $allowZeroHits er TRUE and no result is found
-	 *
-	 */
-	public function searchfordn($attribute, $value, $allowZeroHits) {
-		$ldap = new SimpleSAML_Auth_LDAP($this->hostname,
-			$this->enableTLS,
-			$this->debug,
-			$this->timeout,
-			$this->port,
-			$this->referrals);
-
-		if ($attribute == NULL)
-			$attribute = $this->searchAttributes;
-
-		if ($this->searchUsername !== NULL) {
-			if(!$ldap->bind($this->searchUsername, $this->searchPassword)) {
-				throw new Exception('Error authenticating using search username & password.');
-			}
-		}
-
-		return $ldap->searchfordn($this->searchBase, $attribute,
-			$value, $allowZeroHits);
-	}
-
-	public function getAttributes($dn, $attributes = NULL) {
-		if ($attributes == NULL)
-			$attributes = $this->attributes;
-
-		$ldap = new SimpleSAML_Auth_LDAP($this->hostname,
-			$this->enableTLS,
-			$this->debug,
-			$this->timeout,
-			$this->port,
-			$this->referrals);
-
-		/* Are privs needed to get the attributes? */
-		if ($this->privRead) {
-			/* Yes, rebind with privs */
-			if(!$ldap->bind($this->privUsername, $this->privPassword)) {
-				throw new Exception('Error authenticating using privileged DN & password.');
-			}
-		}
-
-		return $ldap->getAttributes($dn, $attributes);
-	}
+    /**
+     * Array with the base DN(s) for the search.
+     */
+    private $searchBase;
+
+    /**
+     * Additional LDAP filter fields for the search
+     */
+    private $searchFilter;
+
+    /**
+     * The attributes which should match the username.
+     */
+    private $searchAttributes;
+
+
+    /**
+     * The DN pattern we should use to create the DN from the username.
+     */
+    private $dnPattern;
+
+
+    /**
+     * The attributes we should fetch. Can be NULL in which case we will fetch all attributes.
+     */
+    private $attributes;
+
+
+    /**
+     * The user cannot get all attributes, privileged reader required
+     */
+    private $privRead;
+
+
+    /**
+     * The DN we should bind with before we can get the attributes.
+     */
+    private $privUsername;
+
+
+    /**
+     * The password we should bind with before we can get the attributes.
+     */
+    private $privPassword;
+
+
+    /**
+     * Constructor for this configuration parser.
+     *
+     * @param array $config  Configuration.
+     * @param string $location  The location of this configuration. Used for error reporting.
+     */
+    public function __construct($config, $location)
+    {
+        assert('is_array($config)');
+        assert('is_string($location)');
+
+        $this->location = $location;
+
+        // Parse configuration
+        $config = SimpleSAML_Configuration::loadFromArray($config, $location);
+
+        $this->hostname = $config->getString('hostname');
+        $this->enableTLS = $config->getBoolean('enable_tls', false);
+        $this->debug = $config->getBoolean('debug', false);
+        $this->timeout = $config->getInteger('timeout', 0);
+        $this->port = $config->getInteger('port', 389);
+        $this->referrals = $config->getBoolean('referrals', true);
+        $this->searchEnable = $config->getBoolean('search.enable', false);
+        $this->privRead = $config->getBoolean('priv.read', false);
+
+        if ($this->searchEnable) {
+            $this->searchUsername = $config->getString('search.username', null);
+            if ($this->searchUsername !== null) {
+                $this->searchPassword = $config->getString('search.password');
+            }
+
+            $this->searchBase = $config->getArrayizeString('search.base');
+            $this->searchFilter = $config->getString('search.filter', null);
+            $this->searchAttributes = $config->getArray('search.attributes');
+
+        } else {
+            $this->dnPattern = $config->getString('dnpattern');
+        }
+
+        // Are privs needed to get to the attributes?
+        if ($this->privRead) {
+            $this->privUsername = $config->getString('priv.username');
+            $this->privPassword = $config->getString('priv.password');
+        }
+
+        $this->attributes = $config->getArray('attributes', null);
+    }
+
+
+    /**
+     * Attempt to log in using the given username and password.
+     *
+     * Will throw a SimpleSAML_Error_Error('WRONGUSERPASS') if the username or password is wrong.
+     * If there is a configuration problem, an Exception will be thrown.
+     *
+     * @param string $username  The username the user wrote.
+     * @param string $password  The password the user wrote.
+     * @param arrray $sasl_args  Array of SASL options for LDAP bind.
+     * @return array  Associative array with the users attributes.
+     */
+    public function login($username, $password, array $sasl_args = null)
+    {
+        assert('is_string($username)');
+        assert('is_string($password)');
+
+        if (empty($password)) {
+            SimpleSAML\Logger::info($this->location . ': Login with empty password disallowed.');
+            throw new SimpleSAML_Error_Error('WRONGUSERPASS');
+        }
+
+        $ldap = new SimpleSAML_Auth_LDAP($this->hostname, $this->enableTLS, $this->debug, $this->timeout, $this->port, $this->referrals);
+
+        if (!$this->searchEnable) {
+            $ldapusername = addcslashes($username, ',+"\\<>;*');
+            $dn = str_replace('%username%', $ldapusername, $this->dnPattern);
+        } else {
+            if ($this->searchUsername !== null) {
+                if (!$ldap->bind($this->searchUsername, $this->searchPassword)) {
+                    throw new Exception('Error authenticating using search username & password.');
+                }
+            }
+
+            $dn = $ldap->searchfordn($this->searchBase, $this->searchAttributes, $username, true, $this->searchFilter);
+            if ($dn === null) {
+                /* User not found with search. */
+                SimpleSAML\Logger::info($this->location . ': Unable to find users DN. username=\'' . $username . '\'');
+                throw new SimpleSAML_Error_Error('WRONGUSERPASS');
+            }
+        }
+
+        if (!$ldap->bind($dn, $password, $sasl_args)) {
+            SimpleSAML\Logger::info($this->location . ': '. $username . ' failed to authenticate. DN=' . $dn);
+            throw new SimpleSAML_Error_Error('WRONGUSERPASS');
+        }
+
+        /* In case of SASL bind, authenticated and authorized DN may differ */
+        if (isset($sasl_args)) {
+            $dn = $ldap->whoami($this->searchBase, $this->searchAttributes);
+        }
+
+        /* Are privs needed to get the attributes? */
+        if ($this->privRead) {
+            /* Yes, rebind with privs */
+            if (!$ldap->bind($this->privUsername, $this->privPassword)) {
+                throw new Exception('Error authenticating using privileged DN & password.');
+            }
+        }
+
+        return $ldap->getAttributes($dn, $this->attributes);
+    }
+
+
+    /**
+     * Search for a DN.
+     *
+     * @param string|array $attribute
+     * The attribute name(s) searched for. If set to NULL, values from
+     * configuration is used.
+     * @param string $value
+     * The attribute value searched for.
+     * @param bool $allowZeroHits
+     * Determines if the method will throw an exception if no
+     * hits are found. Defaults to FALSE.
+     * @return string
+     * The DN of the matching element, if found. If no element was
+     * found and $allowZeroHits is set to FALSE, an exception will
+     * be thrown; otherwise NULL will be returned.
+     * @throws SimpleSAML_Error_AuthSource if:
+     * - LDAP search encounter some problems when searching cataloge
+     * - Not able to connect to LDAP server
+     * @throws SimpleSAML_Error_UserNotFound if:
+     * - $allowZeroHits is FALSE and no result is found
+     *
+     */
+    public function searchfordn($attribute, $value, $allowZeroHits)
+    {
+        $ldap = new SimpleSAML_Auth_LDAP($this->hostname,
+            $this->enableTLS,
+            $this->debug,
+            $this->timeout,
+            $this->port,
+            $this->referrals);
+
+        if ($attribute == null) {
+            $attribute = $this->searchAttributes;
+        }
+
+        if ($this->searchUsername !== null) {
+            if (!$ldap->bind($this->searchUsername, $this->searchPassword)) {
+                throw new Exception('Error authenticating using search username & password.');
+            }
+        }
+
+        return $ldap->searchfordn($this->searchBase, $attribute,
+            $value, $allowZeroHits);
+    }
+
+    public function getAttributes($dn, $attributes = null)
+    {
+        if ($attributes == null) {
+            $attributes = $this->attributes;
+        }
+
+        $ldap = new SimpleSAML_Auth_LDAP($this->hostname,
+            $this->enableTLS,
+            $this->debug,
+            $this->timeout,
+            $this->port,
+            $this->referrals);
+
+        /* Are privs needed to get the attributes? */
+        if ($this->privRead) {
+            /* Yes, rebind with privs */
+            if (!$ldap->bind($this->privUsername, $this->privPassword)) {
+                throw new Exception('Error authenticating using privileged DN & password.');
+            }
+        }
+        return $ldap->getAttributes($dn, $attributes);
+    }
 
 }