diff --git a/conf/core/usersources.ini.template b/conf/core/usersources.ini.template
index df221ef5f87033444138f2e9e9d3fe6886c696a3..14ad63428550e2548c688b95b66024b800a4db31 100644
--- a/conf/core/usersources.ini.template
+++ b/conf/core/usersources.ini.template
@@ -25,6 +25,7 @@ defaultRealm = PAM
 
 [PAM]
 class = caosdb.server.accessControl.Pam
+; pam_script = ./misc/pam_authentication/pam_authentication.sh
 default_status = ACTIVE
 ;include.user = [uncomment and put your users here]
 ;include.group = [uncomment and put your groups here]
diff --git a/misc/pam_authentication/ldap.conf b/misc/pam_authentication/ldap.conf
new file mode 100644
index 0000000000000000000000000000000000000000..aca5b0491bc937997f7e70efae09d92c55564e67
--- /dev/null
+++ b/misc/pam_authentication/ldap.conf
@@ -0,0 +1,7 @@
+# This file is sourced by the LDAP authentication script
+
+
+# Set the ldap server here.  This is also used to generate a fully qualified
+# user name.
+
+# LDAP_SERVER="example.com"
diff --git a/misc/pam_authentication/ldap_authentication.sh b/misc/pam_authentication/ldap_authentication.sh
new file mode 100755
index 0000000000000000000000000000000000000000..1e3ee2e8da5cc4aed55c55359ae1086e6b7de129
--- /dev/null
+++ b/misc/pam_authentication/ldap_authentication.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+# ** header v3.0
+# This file is a part of the CaosDB Project.
+#
+# Copyright (c) 2020 IndiScale GmbH
+# Copyright (c) 2020 Daniel Hornung <d.hornung@indiscale.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+# ** end header
+
+# Try to authenticate a user ($1) with a password ($2) via LDAP
+
+[[ "$#" == "2" ]] || {
+    echo "call this script with two arguments: user and password"
+    exit 1
+}
+
+# set LDAP_SERVER here
+# e.g. `LDAP_SERVER=example.com`
+exe_dir=$(dirname $0)
+. "$exe_dir/"ldap.conf
+
+testpw() {
+    username="${1}@${LDAP_SERVER}"
+    pw="$2"
+
+    if timeout 5s ldapwhoami -x -H "ldap://$LDAP_SERVER" -D "$username" -w "$pw"; then
+        return 0
+    else
+        ret_code="$?"
+    fi
+
+    # Possibly try a second time
+    if [[ "$ret_code" != "124" ]] ; then
+        return "$ret_code"
+    fi
+
+    ldapwhoami -x -H "ldap://$LDAP_SERVER" -D "$username" -w "$pw"
+
+}
+
+if testpw "$1" "$2" ; then
+    echo "[OK]"
+    exit 0
+else
+    echo "[FAILED]"
+    exit 1
+fi
diff --git a/src/main/java/caosdb/server/accessControl/Pam.java b/src/main/java/caosdb/server/accessControl/Pam.java
index d640a66f4fffdb6254c7d11d696a1f2a1bf5ebf6..606fddb6858968c9ccf363dfd5fb703d4b264913 100644
--- a/src/main/java/caosdb/server/accessControl/Pam.java
+++ b/src/main/java/caosdb/server/accessControl/Pam.java
@@ -254,13 +254,17 @@ public class Pam implements UserSource {
    */
   private boolean isUserExistingNoCache(final String username) {
     logger.trace("Check UnixUser.exists", username);
-    return username != null && UnixUser.exists(username) && isIncorporated(username);
+    // TODO Decide what to do here.  Checking for existence may not always be possible without
+    // credentials.
+
+    // return username != null && UnixUser.exists(username) && isIncorporated(username);
+    return username != null && isIncorporated(username);
   }
 
   /** @see {@link UserSource#isValid(String, String)}. */
   @Override
   public boolean isValid(final String username, final String password) {
-    if (isUserExisting(username)) {
+    if (username != null && isIncorporated(username)) {
       return isValid(getPamScriptCaller(), username, password);
     }
     return false;