Testing spring basic authentication.

Change-Id: I1ceb0f88523ff35f5f10f01ee19000e04bfd8e83
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/spring/BasicAuthenticationManager.java b/full/src/main/java/de/ids_mannheim/korap/authentication/spring/BasicAuthenticationManager.java
new file mode 100644
index 0000000..49ec065
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/spring/BasicAuthenticationManager.java
@@ -0,0 +1,66 @@
+package de.ids_mannheim.korap.authentication.spring;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
+import de.ids_mannheim.korap.config.Scopes;
+import de.ids_mannheim.korap.config.TokenType;
+import de.ids_mannheim.korap.dao.UserDao;
+import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import de.ids_mannheim.korap.user.KorAPUser;
+import de.ids_mannheim.korap.user.TokenContext;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.TimeUtils;
+
+/** * Basic authentication manager is intended to be used with a database. 
+ * It is currently only used for testing using a dummy DAO (@see {@link UserDao}) 
+ * without passwords.
+ * 
+ * @author margaretha
+ *
+ */
+public class BasicAuthenticationManager implements AuthenticationManager{
+
+    @Autowired
+    private KustvaktConfiguration config;
+    @Autowired
+    private EncryptionIface crypto;
+    @Autowired
+    private UserDao dao;
+    
+    @Override
+    public Authentication authenticate (Authentication authentication)
+            throws AuthenticationException {
+
+        String username = (String) authentication.getPrincipal();
+        String password = (String) authentication.getCredentials();
+        
+        TokenContext c = new TokenContext();
+        User user = dao.getAccount(username);
+        if (user instanceof KorAPUser
+                && ((KorAPUser) user).getPassword() != null) {
+            boolean check = crypto.checkHash(password,
+                    ((KorAPUser) user).getPassword());
+
+            if (!check) return null;
+        }
+        
+        c.setUsername(username);
+        c.setExpirationTime(TimeUtils.plusSeconds(this.config.getTokenTTL())
+                .getMillis());
+        c.setTokenType(TokenType.BASIC);
+        // todo: for production mode, set true
+        c.setSecureRequired(false);
+        // EM: is this secure?
+        c.setToken(authentication.toString());
+        c.addContextParameter(Attributes.SCOPES,
+                Scopes.Scope.search.toString());
+        
+        return authentication;
+    }
+
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/spring/KustvaktAuthenticationException.java b/full/src/main/java/de/ids_mannheim/korap/authentication/spring/KustvaktAuthenticationException.java
new file mode 100644
index 0000000..aeb7ff2
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/spring/KustvaktAuthenticationException.java
@@ -0,0 +1,29 @@
+package de.ids_mannheim.korap.authentication.spring;
+
+import org.springframework.security.core.AuthenticationException;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.web.CoreResponseHandler;
+
+public class KustvaktAuthenticationException extends AuthenticationException {
+
+    /**
+     * Auto-generated serian UID
+     */
+    private static final long serialVersionUID = -357703101436703635L;
+    private String notification;
+    
+    public KustvaktAuthenticationException (String msg) {
+        super(msg);
+    }
+
+    public KustvaktAuthenticationException (KustvaktException e) {
+        super(e.getMessage());
+        notification = CoreResponseHandler.buildNotification(e.getStatusCode(),
+                e.getMessage(), e.getEntity());
+    }
+    
+    public String getNotification () {
+        return notification;
+    }
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/spring/KustvaktBasicAuthenticationEntryPoint.java b/full/src/main/java/de/ids_mannheim/korap/authentication/spring/KustvaktBasicAuthenticationEntryPoint.java
new file mode 100644
index 0000000..de044c0
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/spring/KustvaktBasicAuthenticationEntryPoint.java
@@ -0,0 +1,30 @@
+package de.ids_mannheim.korap.authentication.spring;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
+
+public class KustvaktBasicAuthenticationEntryPoint
+        extends BasicAuthenticationEntryPoint {
+
+    @Override
+    public void commence (HttpServletRequest request,
+            HttpServletResponse response, AuthenticationException authException)
+            throws IOException, ServletException {
+        super.commence(request, response, authException);
+
+        String notification = ((KustvaktAuthenticationException) authException)
+                .getNotification();
+
+        PrintWriter writer = response.getWriter();
+        writer.write(notification);
+        writer.flush();
+        writer.close();
+    }
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/spring/LDAPAuthenticationManager.java b/full/src/main/java/de/ids_mannheim/korap/authentication/spring/LDAPAuthenticationManager.java
new file mode 100644
index 0000000..a094d9c
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/spring/LDAPAuthenticationManager.java
@@ -0,0 +1,94 @@
+package de.ids_mannheim.korap.authentication.spring;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+
+import com.unboundid.ldap.sdk.LDAPException;
+
+import de.ids_mannheim.korap.authentication.LdapAuth3;
+import de.ids_mannheim.korap.config.FullConfiguration;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+
+public class LDAPAuthenticationManager implements AuthenticationManager {
+
+    private static Logger jlog =
+            LoggerFactory.getLogger(LDAPAuthenticationManager.class);
+    @Autowired
+    private FullConfiguration config;
+
+    @Override
+    public Authentication authenticate (Authentication authentication)
+            throws AuthenticationException {
+
+        String username = (String) authentication.getPrincipal();
+        String password = (String) authentication.getCredentials();
+
+        // just to make sure that the plain password does not appear anywhere in
+        // the logs!
+
+        System.out.printf("Debug: authenticateIdM: entering for '%s'...\n",
+                username);
+
+        /**
+         * wozu Apache Validatoren für User/Passwort für IdM/LDAP? siehe
+         * validation.properties. Abgeschaltet 21.04.17/FB try {
+         * validator.validateEntry(username, Attributes.USERNAME); } catch
+         * (KustvaktException e) { throw new WrappedException(e,
+         * StatusCodes.LOGIN_FAILED, username); }
+         */
+        if (username == null || username.isEmpty() || password == null
+                || password.isEmpty()) {
+            throw new KustvaktAuthenticationException(
+                    new KustvaktException(StatusCodes.BAD_CREDENTIALS,
+                            "Missing username or password."));
+        }
+
+        // LDAP Access:
+        try {
+            // todo: unknown = ...
+            int ret =
+                    LdapAuth3.login(username, password, config.getLdapConfig());
+            System.out.printf(
+                    "Debug: autenticationIdM: Ldap.login(%s) returns: %d.\n",
+                    username, ret);
+            if (ret != LdapAuth3.LDAP_AUTH_ROK) {
+                jlog.error("LdapAuth3.login(username='{}') returns '{}'='{}'!",
+                        username, ret, LdapAuth3.getErrMessage(ret));
+
+                // mask exception to disable user guessing in possible attacks
+                /*
+                 * by Hanl throw new WrappedException(new
+                 * KustvaktException(username, StatusCodes.BAD_CREDENTIALS),
+                 * StatusCodes.LOGIN_FAILED, username);
+                 */
+                throw new KustvaktAuthenticationException(new KustvaktException(
+                        username, StatusCodes.LDAP_BASE_ERRCODE + ret,
+                        LdapAuth3.getErrMessage(ret), username));
+            }
+        }
+        catch (LDAPException e) {
+
+            jlog.error("Error: username='{}' -> '{}'!", username, e);
+            // mask exception to disable user guessing in possible attacks
+            /*
+             * by Hanl: throw new WrappedException(new
+             * KustvaktException(username, StatusCodes.BAD_CREDENTIALS),
+             * StatusCodes.LOGIN_FAILED, username);
+             */
+            throw new KustvaktAuthenticationException(new KustvaktException(
+                    username,
+                    StatusCodes.LDAP_BASE_ERRCODE + LdapAuth3.LDAP_AUTH_RINTERR,
+                    LdapAuth3.getErrMessage(LdapAuth3.LDAP_AUTH_RINTERR),
+                    username));
+        }
+
+        jlog.debug("Authentication done: " + username);
+        return authentication;
+    }
+
+}