diff --git a/modules/negotiate/lib/Auth/Source/Negotiate.php b/modules/negotiate/lib/Auth/Source/Negotiate.php
index 060e8e86f7d31fb243c635970ff32950f810c4be..55d3e7413cecfa5ed39d20c1a06b9021f1c86da3 100644
--- a/modules/negotiate/lib/Auth/Source/Negotiate.php
+++ b/modules/negotiate/lib/Auth/Source/Negotiate.php
@@ -1,335 +1,365 @@
 <?php
 
+
 /**
- * The Negotiate module. Allows for password-less, secure login by
- * Kerberos and Negotiate.
+ * The Negotiate module. Allows for password-less, secure login by Kerberos and Negotiate.
  *
- * @author Mathias Meisfjordskar, University of Oslo.
- * 	   <mathias.meisfjordskar@usit.uio.no>
- * @package simpleSAMLphp
+ * @author Mathias Meisfjordskar, University of Oslo <mathias.meisfjordskar@usit.uio.no>
+ * @package SimpleSAMLphp
  */
-
-class sspmod_negotiate_Auth_Source_Negotiate extends SimpleSAML_Auth_Source {
-
-	// Constants used in the module
-	const STAGEID = 'sspmod_negotiate_Auth_Source_Negotiate.StageId';
-
-	private $config;
-	protected $ldap = NULL;
-	protected $backend = '';
-	protected $hostname = '';
-	protected $port = 389;
-	protected $referrals = true;
-	protected $enableTLS = false;
-	protected $debugLDAP = false;
-	protected $timeout = 30;
-	protected $keytab = '';
-	protected $base = array();
-	protected $attr = 'uid';
-	protected $subnet = null;
-	protected $admin_user = null;
-	protected $admin_pw = null;
-	protected $attributes = null;
-
-	/**
-	 * 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)');
-
-		if(!extension_loaded('krb5'))
-			throw new Exception('KRB5 Extension not installed');
-
-		// Call the parent constructor first, as required by the interface.
-		parent::__construct($info, $config);
-
-		$config = SimpleSAML_Configuration::loadFromArray($config);;
-
-		$this->backend = $config->getString('fallback');
-		$this->hostname = $config->getString('hostname');
-		$this->port = $config->getInteger('port', 389);
-		$this->referrals = $config->getBoolean('referrals', TRUE);
-		$this->enableTLS = $config->getBoolean('enable_tls', FALSE);
-		$this->debugLDAP = $config->getBoolean('debugLDAP', FALSE);
-		$this->timeout = $config->getInteger('timeout', 30);
-		$this->keytab = $config->getString('keytab');
-		$this->base = $config->getArrayizeString('base');
-		$this->attr = $config->getString('attr', 'uid');
-		$this->subnet = $config->getArray('subnet', NULL);
-		$this->admin_user = $config->getString('adminUser', NULL);
-		$this->admin_pw = $config->getString('adminPassword', NULL);
-		$this->attributes = $config->getArray('attributes', NULL);
-
-	}
-
-	/**
-	 * The inner workings of the module.
-	 *
-	 * Checks to see if client is in the defined subnets (if
-	 * defined in config). Sends the client a 401 Negotiate and
-	 * responds to the result. If the client fails to provide a
-	 * proper Kerberos ticket, the login process is handed over to
-	 * the 'fallback' module defined in the config.
-	 *
-	 * LDAP is used as a user metadata source.
-	 *
-	 * @param array &$state	 Information about the current authentication.
-	 */
-	public function authenticate(&$state) {
-		assert('is_array($state)');
-
-		// Set the default backend to config
-		$state['LogoutState'] = array(
-			'negotiate:backend' => $this->backend,
-			);
-		$state['negotiate:authId'] = $this->authId;
-
-
-		// Check for disabled SPs. The disable flag is store in the SP
-		// metadata.
-		if (array_key_exists('SPMetadata', $state) && $this->spDisabledInMetadata($state['SPMetadata']))
-			$this->fallBack($state);
-		// Go straight to fallback if Negotiate is disabled or if you are
-		// sent back to the IdP directly from the SP after having logged out
-		$session = SimpleSAML_Session::getSessionFromRequest();
-		$disabled = $session->getData('negotiate:disable', 'session');
-
-		if ($disabled ||
-		    (!empty($_COOKIE['NEGOTIATE_AUTOLOGIN_DISABLE_PERMANENT']) &&
-		     $_COOKIE['NEGOTIATE_AUTOLOGIN_DISABLE_PERMANENT'] == 'True')) {
-			SimpleSAML_Logger::debug('Negotiate - session disabled. falling back');
-			$this->fallBack($state);
-			// Never executed
-			assert('FALSE');
-		}
-		$mask = $this->checkMask();
-		if (!$mask) {
-			$this->fallBack($state);
-			// Never executed
-			assert('FALSE');
-		}
-
-		SimpleSAML_Logger::debug('Negotiate - authenticate(): looking for Negotate');
-		if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
-			SimpleSAML_Logger::debug('Negotiate - authenticate(): Negotate found');
-			$this->ldap = new SimpleSAML_Auth_LDAP($this->hostname, $this->enableTLS, $this->debugLDAP, $this->timeout, $this->port, $this->referrals);
-
-			list($mech, $data) = explode(' ', $_SERVER['HTTP_AUTHORIZATION'],2);
-			if(strtolower($mech) == 'basic')
-				SimpleSAML_Logger::debug('Negotiate - authenticate(): Basic found. Skipping.');
-			else if(strtolower($mech) != 'negotiate')
-				SimpleSAML_Logger::debug('Negotiate - authenticate(): No "Negotiate" found. Skipping.');
-
-			$auth = new KRB5NegotiateAuth($this->keytab);
-			// Atempt Kerberos authentication
-			try {
-				$reply = $auth->doAuthentication();
-			} catch (Exception $e) {
-				SimpleSAML_Logger::error('Negotiate - authenticate(): doAuthentication() exception: '. $e->getMessage());
-				$reply = NULL;
-			}
-
-			if($reply) {
-				// Success. Krb TGS recieved.
-				$user = $auth->getAuthenticatedUser();
-				SimpleSAML_Logger::info('Negotiate - authenticate(): '. $user . ' authenticated.');
-				$lookup = $this->lookupUserData($user);
-				if ($lookup) {
-					$state['Attributes'] = $lookup;
-					// Override the backend so logout will know what to look for.
-					$state['LogoutState'] = array(
-						'negotiate:backend' => NULL,
-						);
-					SimpleSAML_Logger::info('Negotiate - authenticate(): '. $user . ' authorized.');
-					SimpleSAML_Auth_Source::completeAuth($state);
-					// Never reached.
-					assert('FALSE');
-				}
-			} else {
-				// Some error in the recieved ticket. Expired?
-				SimpleSAML_Logger::info('Negotiate - authenticate(): Kerberos authN failed. Skipping.');
-			}
-		} else {
-			// No auth token. Send it.
-			SimpleSAML_Logger::debug('Negotiate - authenticate(): Sending Negotiate.');
-			// Save the $state array, so that we can restore if after a redirect
-			SimpleSAML_Logger::debug('Negotiate - fallback: '.$state['LogoutState']['negotiate:backend']);
-			$id = SimpleSAML_Auth_State::saveState($state, self::STAGEID);
-			$params = array('AuthState' => $id);
-
-			$this->sendNegotiate($params);
-			exit;
-		}
-
-		SimpleSAML_Logger::info('Negotiate - authenticate(): Client failed Negotiate. Falling back');
-		$this->fallBack($state);
-		/* The previous function never returns, so this code is never
-		   executed */
-		assert('FALSE');
-	}
-
-	public function spDisabledInMetadata($spMetadata) {
-		if (array_key_exists('negotiate:disable', $spMetadata)) {
-			if ($spMetadata['negotiate:disable'] == TRUE) {
-				SimpleSAML_Logger::debug('Negotiate - SP disabled. falling back');
-				return true;
-			} else {
-				SimpleSAML_Logger::debug('Negotiate - SP disable flag found but set to FALSE');
-			}
-		} else {
-			SimpleSAML_Logger::debug('Negotiate - SP disable flag not found');
-		}
-		return False;
-	}
-
-	/**
-	 * checkMask() looks up the subnet config option and verifies
-	 * that the client is within that range.
-	 *
-	 * Will return TRUE if no subnet option is configured.
-	 *
-	 * @return boolean
-	 */
-        public function checkMask() {
-		// No subnet means all clients are accepted.
-		if ($this->subnet === NULL)
-			return TRUE;
-		$ip = $_SERVER['REMOTE_ADDR'];
-		foreach ($this->subnet as $cidr) {
-			$ret = SimpleSAML\Utils\Net::ipCIDRcheck($cidr);
-			if ($ret) {
-				SimpleSAML_Logger::debug('Negotiate: Client "'.$ip.'" matched subnet.');
-				return TRUE;
-			}
-		}
-		SimpleSAML_Logger::debug('Negotiate: Client "'.$ip.'" did not match subnet.');
-		return FALSE;
-	}
-
-	/**
-	 * Send the actual headers and body of the 401. Embedded in
-	 * the body is a post that is triggered by JS if the client
-	 * wants to show the 401 message.
-	 *
-	 * @param array $params additional parameters to the URL in
-	 *			the URL in the body
-	 */
-	protected function sendNegotiate($params) {
-		$url = SimpleSAML_Module::getModuleURL('negotiate/backend.php', $params);
-
-		header('HTTP/1.1 401 Unauthorized');
-		header('WWW-Authenticate: Negotiate',false);
-		echo '
+class sspmod_negotiate_Auth_Source_Negotiate extends SimpleSAML_Auth_Source
+{
+
+    // Constants used in the module
+    const STAGEID = 'sspmod_negotiate_Auth_Source_Negotiate.StageId';
+
+    protected $ldap = null;
+    protected $backend = '';
+    protected $hostname = '';
+    protected $port = 389;
+    protected $referrals = true;
+    protected $enableTLS = false;
+    protected $debugLDAP = false;
+    protected $timeout = 30;
+    protected $keytab = '';
+    protected $base = array();
+    protected $attr = 'uid';
+    protected $subnet = null;
+    protected $admin_user = null;
+    protected $admin_pw = null;
+    protected $attributes = null;
+
+
+    /**
+     * Constructor for this authentication source.
+     *
+     * @param array $info Information about this authentication source.
+     * @param array $config The configuration of the module
+     *
+     * @throws Exception If the KRB5 extension is not installed or active.
+     */
+    public function __construct($info, $config)
+    {
+        assert('is_array($info)');
+        assert('is_array($config)');
+
+        if (!extension_loaded('krb5')) {
+            throw new Exception('KRB5 Extension not installed');
+        }
+
+        // call the parent constructor first, as required by the interface
+        parent::__construct($info, $config);
+
+        $config = SimpleSAML_Configuration::loadFromArray($config);
+
+        $this->backend = $config->getString('fallback');
+        $this->hostname = $config->getString('hostname');
+        $this->port = $config->getInteger('port', 389);
+        $this->referrals = $config->getBoolean('referrals', true);
+        $this->enableTLS = $config->getBoolean('enable_tls', false);
+        $this->debugLDAP = $config->getBoolean('debugLDAP', false);
+        $this->timeout = $config->getInteger('timeout', 30);
+        $this->keytab = $config->getString('keytab');
+        $this->base = $config->getArrayizeString('base');
+        $this->attr = $config->getString('attr', 'uid');
+        $this->subnet = $config->getArray('subnet', null);
+        $this->admin_user = $config->getString('adminUser', null);
+        $this->admin_pw = $config->getString('adminPassword', null);
+        $this->attributes = $config->getArray('attributes', null);
+    }
+
+
+    /**
+     * The inner workings of the module.
+     *
+     * Checks to see if client is in the defined subnets (if defined in config). Sends the client a 401 Negotiate and
+     * responds to the result. If the client fails to provide a proper Kerberos ticket, the login process is handed over
+     * to the 'fallback' module defined in the config.
+     *
+     * LDAP is used as a user metadata source.
+     *
+     * @param array &$state Information about the current authentication.
+     */
+    public function authenticate(&$state)
+    {
+        assert('is_array($state)');
+
+        // set the default backend to config
+        $state['LogoutState'] = array(
+            'negotiate:backend' => $this->backend,
+        );
+        $state['negotiate:authId'] = $this->authId;
+
+
+        // check for disabled SPs. The disable flag is store in the SP metadata
+        if (array_key_exists('SPMetadata', $state) && $this->spDisabledInMetadata($state['SPMetadata'])) {
+            $this->fallBack($state);
+        }
+        /* Go straight to fallback if Negotiate is disabled or if you are sent back to the IdP directly from the SP
+        after having logged out. */
+        $session = SimpleSAML_Session::getSessionFromRequest();
+        $disabled = $session->getData('negotiate:disable', 'session');
+
+        if ($disabled ||
+            (!empty($_COOKIE['NEGOTIATE_AUTOLOGIN_DISABLE_PERMANENT']) &&
+                $_COOKIE['NEGOTIATE_AUTOLOGIN_DISABLE_PERMANENT'] == 'True')
+        ) {
+            SimpleSAML_Logger::debug('Negotiate - session disabled. falling back');
+            $this->fallBack($state);
+            // never executed
+            assert('FALSE');
+        }
+        $mask = $this->checkMask();
+        if (!$mask) {
+            $this->fallBack($state);
+            // never executed
+            assert('FALSE');
+        }
+
+        SimpleSAML_Logger::debug('Negotiate - authenticate(): looking for Negotate');
+        if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
+            SimpleSAML_Logger::debug('Negotiate - authenticate(): Negotate found');
+            $this->ldap = new SimpleSAML_Auth_LDAP(
+                $this->hostname,
+                $this->enableTLS,
+                $this->debugLDAP,
+                $this->timeout,
+                $this->port,
+                $this->referrals
+            );
+
+            list($mech, $data) = explode(' ', $_SERVER['HTTP_AUTHORIZATION'], 2);
+            if (strtolower($mech) == 'basic') {
+                SimpleSAML_Logger::debug('Negotiate - authenticate(): Basic found. Skipping.');
+            } else {
+                if (strtolower($mech) != 'negotiate') {
+                    SimpleSAML_Logger::debug('Negotiate - authenticate(): No "Negotiate" found. Skipping.');
+                }
+            }
+
+            $auth = new KRB5NegotiateAuth($this->keytab);
+            // attempt Kerberos authentication
+            try {
+                $reply = $auth->doAuthentication();
+            } catch (Exception $e) {
+                SimpleSAML_Logger::error('Negotiate - authenticate(): doAuthentication() exception: '.$e->getMessage());
+                $reply = null;
+            }
+
+            if ($reply) {
+                // success! krb TGS received
+                $user = $auth->getAuthenticatedUser();
+                SimpleSAML_Logger::info('Negotiate - authenticate(): '.$user.' authenticated.');
+                $lookup = $this->lookupUserData($user);
+                if ($lookup) {
+                    $state['Attributes'] = $lookup;
+                    // Override the backend so logout will know what to look for.
+                    $state['LogoutState'] = array(
+                        'negotiate:backend' => null,
+                    );
+                    SimpleSAML_Logger::info('Negotiate - authenticate(): '.$user.' authorized.');
+                    SimpleSAML_Auth_Source::completeAuth($state);
+                    // Never reached.
+                    assert('FALSE');
+                }
+            } else {
+                // Some error in the recieved ticket. Expired?
+                SimpleSAML_Logger::info('Negotiate - authenticate(): Kerberos authN failed. Skipping.');
+            }
+        } else {
+            // No auth token. Send it.
+            SimpleSAML_Logger::debug('Negotiate - authenticate(): Sending Negotiate.');
+            // Save the $state array, so that we can restore if after a redirect
+            SimpleSAML_Logger::debug('Negotiate - fallback: '.$state['LogoutState']['negotiate:backend']);
+            $id = SimpleSAML_Auth_State::saveState($state, self::STAGEID);
+            $params = array('AuthState' => $id);
+
+            $this->sendNegotiate($params);
+            exit;
+        }
+
+        SimpleSAML_Logger::info('Negotiate - authenticate(): Client failed Negotiate. Falling back');
+        $this->fallBack($state);
+        /* The previous function never returns, so this code is never
+           executed */
+        assert('FALSE');
+    }
+
+
+    public function spDisabledInMetadata($spMetadata)
+    {
+        if (array_key_exists('negotiate:disable', $spMetadata)) {
+            if ($spMetadata['negotiate:disable'] == true) {
+                SimpleSAML_Logger::debug('Negotiate - SP disabled. falling back');
+                return true;
+            } else {
+                SimpleSAML_Logger::debug('Negotiate - SP disable flag found but set to FALSE');
+            }
+        } else {
+            SimpleSAML_Logger::debug('Negotiate - SP disable flag not found');
+        }
+        return false;
+    }
+
+
+    /**
+     * checkMask() looks up the subnet config option and verifies
+     * that the client is within that range.
+     *
+     * Will return TRUE if no subnet option is configured.
+     *
+     * @return boolean
+     */
+    public function checkMask()
+    {
+        // No subnet means all clients are accepted.
+        if ($this->subnet === null) {
+            return true;
+        }
+        $ip = $_SERVER['REMOTE_ADDR'];
+        foreach ($this->subnet as $cidr) {
+            $ret = SimpleSAML\Utils\Net::ipCIDRcheck($cidr);
+            if ($ret) {
+                SimpleSAML_Logger::debug('Negotiate: Client "'.$ip.'" matched subnet.');
+                return true;
+            }
+        }
+        SimpleSAML_Logger::debug('Negotiate: Client "'.$ip.'" did not match subnet.');
+        return false;
+    }
+
+
+    /**
+     * Send the actual headers and body of the 401. Embedded in the body is a post that is triggered by JS if the client
+     * wants to show the 401 message.
+     *
+     * @param array $params additional parameters to the URL in the URL in the body.
+     */
+    protected function sendNegotiate($params)
+    {
+        $url = htmlspecialchars(SimpleSAML_Module::getModuleURL('negotiate/backend.php', $params));
+        $json_url = json_encode($url);
+
+        header('HTTP/1.1 401 Unauthorized');
+        header('WWW-Authenticate: Negotiate', false);
+        echo <<<EOF
 <html>
-<head>
-<script type="text/javascript">window.location = '.json_encode(htmlspecialchars($url)).'</script>
-<title>Redirect to login</title>
-</head>
+ <head>
+  <script type="text/javascript">window.location = $json_url</script>
+  <title>Redirect to login</title>
+ </head>
 <body>
-Your browser seems to have Javascript disabled. Please
-click <a href="'.htmlspecialchars($url).'">here</a>.
+ <p>Your browser seems to have Javascript disabled. Please click <a href="$url">here</a>.</p>
 </body>
-</html> ';
-
-	}
-
-	/**
-	 * Passes control of the login process to a different module.
-	 *
-	 * @param string $state	 Information about the current authentication.
-	 */
-	public static function fallBack(&$state) {
-		$authId = $state['LogoutState']['negotiate:backend'];
-
-		if ($authId === NULL) {
-			$msg = "This code should never be reached.";
-			throw new SimpleSAML_Error_AuthSource($msg);
-		}
-		$source = SimpleSAML_Auth_Source::getById($authId);
-
-		try {
-			$source->authenticate($state);
-		} catch (SimpleSAML_Error_Exception $e) {
-			SimpleSAML_Auth_State::throwException($state, $e);
-		} catch (Exception $e) {
-			$e = new SimpleSAML_Error_UnserializableException($e);
-			SimpleSAML_Auth_State::throwException($state, $e);
-		}
-		// fallBack never returns after loginCompleted()
-		SimpleSAML_Logger::debug('Negotiate: backend returned');
-		self::loginCompleted($state);
-	}
-
-	/**
-	 * Strips away the realm of the Kerberos identifier, looks up
-	 * what attributes to fetch from SP metadata and searches the
-	 * directory.
-	 *
-	 * @param string $user	The Kerberos user identifier
-	 * @return string	The DN to the user or NULL if not found
-	 */
-	protected function lookupUserData($user) {
-		// Kerberos usernames include realm. Strip that away.
-		$pos = strpos($user, '@');
-		if ($pos === false)
-			return NULL;
-		$uid = substr($user, 0, $pos);
-
-		$this->adminBind();
-		try {
-			$dn = $this->ldap->searchfordn($this->base, $this->attr, $uid);
-			return $this->ldap->getAttributes($dn, $this->attributes);
-		} catch (SimpleSAML_Error_Exception $e) {
-			SimpleSAML_Logger::debug('Negotiate - ldap lookup failed: '. $e);
-			return NULL;
-		}
-	}
-
-	/**
-	 * Elevates the LDAP connection to allow restricted lookups if
-	 * so configured. Does nothing if not.
-	 */
-	protected function adminBind() {
-		if ($this->admin_user === NULL) {
-			// No admin user.
-			return;
-		}
-		SimpleSAML_Logger::debug('Negotiate - authenticate(): Binding as system user ' . var_export($this->admin_user, TRUE));
-
-		if(!$this->ldap->bind($this->admin_user, $this->admin_pw)){
-			$msg = 'Unable to authenticate system user (LDAP_INVALID_CREDENTIALS) ' . var_export($this->admin_user, TRUE);
-			SimpleSAML_Logger::error('Negotiate - authenticate(): ' . $msg);
-			throw new SimpleSAML_Error_AuthSource($msg);
-		}
-	}
-
-	/**
-	 * Log out from this authentication source.
-	 *
-	 * This method either logs the user out from Negotiate or passes the
-	 * logout call to the fallback module.
-	 *
-	 * @param array &$state	 Information about the current logout operation.
-	 */
-	public function logout(&$state) {
-		assert('is_array($state)');
-		/* Get the source that was used to authenticate */
-		$authId = $state['negotiate:backend'];
-		SimpleSAML_Logger::debug('Negotiate - logout has the following authId: "'.$authId.'"');
-
-		if ($authId === NULL) {
-			$session = SimpleSAML_Session::getSessionFromRequest();
-			$session->setData('negotiate:disable', 'session', TRUE, 24*60*60);
-			parent::logout($state);
-		} else {
-			$source = SimpleSAML_Auth_Source::getById($authId);
-			$source->logout($state);
-		}
-	}
-
+</html>
+EOF;
+    }
+
+
+    /**
+     * Passes control of the login process to a different module.
+     *
+     * @param string $state Information about the current authentication.
+     *
+     * @throws SimpleSAML_Error_Error If couldn't determine the auth source.
+     * @throws SimpleSAML_Error_Exception
+     * @throws Exception
+     */
+    public static function fallBack(&$state)
+    {
+        $authId = $state['LogoutState']['negotiate:backend'];
+
+        if ($authId === null) {
+            throw new SimpleSAML_Error_Error(500, "Unable to determine auth source.");
+        }
+        $source = SimpleSAML_Auth_Source::getById($authId);
+
+        try {
+            $source->authenticate($state);
+        } catch (SimpleSAML_Error_Exception $e) {
+            SimpleSAML_Auth_State::throwException($state, $e);
+        } catch (Exception $e) {
+            $e = new SimpleSAML_Error_UnserializableException($e);
+            SimpleSAML_Auth_State::throwException($state, $e);
+        }
+        // fallBack never returns after loginCompleted()
+        SimpleSAML_Logger::debug('Negotiate: backend returned');
+        self::loginCompleted($state);
+    }
+
+
+    /**
+     * Strips away the realm of the Kerberos identifier, looks up what attributes to fetch from SP metadata and
+     * searches the directory.
+     *
+     * @param string $user The Kerberos user identifier.
+     *
+     * @return string The DN to the user or NULL if not found.
+     */
+    protected function lookupUserData($user)
+    {
+        // Kerberos user names include realm. Strip that away.
+        $pos = strpos($user, '@');
+        if ($pos === false) {
+            return null;
+        }
+        $uid = substr($user, 0, $pos);
+
+        $this->adminBind();
+        try {
+            $dn = $this->ldap->searchfordn($this->base, $this->attr, $uid);
+            return $this->ldap->getAttributes($dn, $this->attributes);
+        } catch (SimpleSAML_Error_Exception $e) {
+            SimpleSAML_Logger::debug('Negotiate - ldap lookup failed: '.$e);
+            return null;
+        }
+    }
+
+
+    /**
+     * Elevates the LDAP connection to allow restricted lookups if
+     * so configured. Does nothing if not.
+     */
+    protected function adminBind()
+    {
+        if ($this->admin_user === null) {
+            // no admin user
+            return;
+        }
+        SimpleSAML_Logger::debug(
+            'Negotiate - authenticate(): Binding as system user '.var_export($this->admin_user, true)
+        );
+
+        if (!$this->ldap->bind($this->admin_user, $this->admin_pw)) {
+            $msg = 'Unable to authenticate system user (LDAP_INVALID_CREDENTIALS) '.var_export($this->admin_user, true);
+            SimpleSAML_Logger::error('Negotiate - authenticate(): '.$msg);
+            throw new SimpleSAML_Error_AuthSource($msg);
+        }
+    }
+
+
+    /**
+     * Log out from this authentication source.
+     *
+     * This method either logs the user out from Negotiate or passes the
+     * logout call to the fallback module.
+     *
+     * @param array &$state Information about the current logout operation.
+     */
+    public function logout(&$state)
+    {
+        assert('is_array($state)');
+        // get the source that was used to authenticate
+        $authId = $state['negotiate:backend'];
+        SimpleSAML_Logger::debug('Negotiate - logout has the following authId: "'.$authId.'"');
+
+        if ($authId === null) {
+            $session = SimpleSAML_Session::getSessionFromRequest();
+            $session->setData('negotiate:disable', 'session', true, 24 * 60 * 60);
+            parent::logout($state);
+        } else {
+            $source = SimpleSAML_Auth_Source::getById($authId);
+            $source->logout($state);
+        }
+    }
 }
-