changeset 545:8e3f57e2f4af openid

Change openID authentication to a filter. Currently authentication works only once as we don't store session information and repeated try to authenticate will use the same nonce.
author Andre Heinecke <andre.heinecke@intevation.de>
date Wed, 25 Feb 2015 16:56:12 +0100
parents 04e254571b8a
children b691c8697e6f
files pom.xml src/main/java/de/intevation/lada/rest/ProbeService.java src/main/java/de/intevation/lada/util/auth/OpenIDAuthentication.java src/main/java/de/intevation/lada/util/auth/OpenIDFilter.java
diffstat 4 files changed, 228 insertions(+), 208 deletions(-) [+]
line wrap: on
line diff
--- a/pom.xml	Wed Feb 25 16:03:35 2015 +0100
+++ b/pom.xml	Wed Feb 25 16:56:12 2015 +0100
@@ -60,7 +60,11 @@
             <groupId>org.jboss.spec.javax.json</groupId>
             <artifactId>jboss-json-api_1.0_spec</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <version>1.0.2.Final</version>
+        </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
--- a/src/main/java/de/intevation/lada/rest/ProbeService.java	Wed Feb 25 16:03:35 2015 +0100
+++ b/src/main/java/de/intevation/lada/rest/ProbeService.java	Wed Feb 25 16:56:12 2015 +0100
@@ -67,7 +67,7 @@
 
     /* The authentication module.*/
     @Inject
-    @AuthenticationConfig(type=AuthenticationType.OPENID)
+    @AuthenticationConfig(type=AuthenticationType.NONE)
     private Authentication authentication;
 
     /* The authorization module.*/
--- a/src/main/java/de/intevation/lada/util/auth/OpenIDAuthentication.java	Wed Feb 25 16:03:35 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/* Copyright (C) 2015 by Bundesamt fuer Strahlenschutz
- * Software engineering by Intevation GmbH
- *
- * This file is Free Software under the GNU GPL (v>=3) 
- * and comes with ABSOLUTELY NO WARRANTY! Check out 
- * the documentation coming with IMIS-Labordaten-Application for details. 
- */
-package de.intevation.lada.util.auth;
-
-import java.util.Map;
-import java.util.List;
-import java.util.LinkedHashMap;
-import java.net.URLDecoder;
-
-import javax.inject.Inject;
-import javax.ejb.Stateless;
-import javax.ws.rs.core.HttpHeaders;
-
-import de.intevation.lada.util.annotation.AuthenticationConfig;
-
-import org.openid4java.association.AssociationSessionType;
-import org.openid4java.association.AssociationException;
-import org.openid4java.consumer.ConsumerManager;
-import org.openid4java.consumer.ConsumerException;
-import org.openid4java.consumer.InMemoryConsumerAssociationStore;
-import org.openid4java.consumer.InMemoryNonceVerifier;
-import org.openid4java.message.ParameterList;
-import org.openid4java.consumer.VerificationResult;
-import org.openid4java.discovery.DiscoveryInformation;
-import org.openid4java.discovery.Identifier;
-import org.openid4java.discovery.DiscoveryException;
-import org.openid4java.message.MessageException;
-import org.openid4java.message.AuthRequest;
-
-import org.apache.log4j.Logger;
-
-public class OpenIDAuthentication implements Authentication {
-
-    /** The name of the header field used to transport OpenID parameters.*/
-    private static final String OID_HEADER_FIELD= "X-OPENID-PARAMS";
-
-    /** The identity provider we accept here. */
-    private static final String IDENTITY_PROVIDER =
-        "http://localhost:8087/account";
-
-    /** This is currently a faked dummy */
-    private static final String RETURN_URL =
-        "http://localhost:8086/consumer-servlet/consumer?is_return=true";
-
-    private static final Logger logger =
-        Logger.getLogger(OpenIDAuthentication.class);
-
-    private ConsumerManager manager;
-
-    private Map<String,String> idParams;
-
-    boolean discoveryDone = false;
-
-    private DiscoveryInformation discovered;
-
-    private boolean discoverServer() {
-        /* Perform discovery on the configured IDENTITY_PROVIDER */
-        List discoveries = null;
-        try {
-            discoveries = manager.discover(IDENTITY_PROVIDER);
-        } catch (DiscoveryException e) {
-            logger.debug("Discovery failed: " + e.getMessage());
-            return false;
-        }
-
-        if (discoveries == null || discoveries.isEmpty()) {
-            logger.error(
-                    "Failed discovery step. OpenID provider unavailable?");
-            return false;
-        }
-
-        /* Add association for the discovered information */
-        discovered = manager.associate(discoveries);
-
-        /* Validate the parameters. */
-        logger.debug("After discovery.");
-        try {
-            AuthRequest authReq = manager.authenticate(discovered, RETURN_URL);
-            logger.debug("Authenticate with: " + authReq.getDestinationUrl(true));
-        } catch (MessageException e) {
-            logger.debug("Failed to create the Authentication request: " +
-                    e.getMessage());
-        } catch (ConsumerException e) {
-            logger.debug("Error in consumer manager: " +
-                    e.getMessage());
-        }
-        logger.debug("After authenticate.");
-        return true;
-    }
-
-    public OpenIDAuthentication() {
-        manager = new ConsumerManager();
-        /* TODO: Check for alternative configs. */
-        manager.setAssociations(new InMemoryConsumerAssociationStore());
-        manager.setNonceVerifier(new InMemoryNonceVerifier(50000));
-        manager.setMinAssocSessEnc(AssociationSessionType.DH_SHA256);
-        discoveryDone = discoverServer();
-    }
-
-    /** Split up the OpenID response query provided in the header.
-     *
-     * @param responseQuery The query provided in the header field.
-     * @return The query as ParameterList or null on error.
-     */
-    private ParameterList splitParams(String responseQuery) {
-        Map<String, String> queryMap =
-            new LinkedHashMap<String, String>();
-        final String[] pairs = responseQuery.split("&");
-        for (String pair : pairs) {
-            final int idx = pair.indexOf("=");
-            if (idx <= 0) {
-                logger.debug("Invalid query.");
-                return null;
-            }
-            try {
-                final String key = URLDecoder.decode(
-                        pair.substring(0, idx), "UTF-8");
-
-                if (queryMap.containsKey(key)) {
-                    logger.debug("Invalid query. Duplicate key: " + key);
-                    return null;
-                }
-                final String value = URLDecoder.decode(
-                        pair.substring(idx + 1), "UTF-8");
-                queryMap.put(key, value);
-            } catch (java.io.UnsupportedEncodingException e) {
-                logger.error("UTF-8 unkown?!");
-                return null;
-            }
-        }
-        if (queryMap.isEmpty()) {
-            logger.debug("Empty query.");
-            return null;
-        }
-        return new ParameterList(queryMap);
-    }
-
-    private boolean checkOpenIDHeader(HttpHeaders headers) {
-        /* First check if there are is anything provided */
-        List<String> oidParamString = headers.getRequestHeader(
-                OID_HEADER_FIELD);
-        if (oidParamString == null) {
-            logger.debug("Header " + OID_HEADER_FIELD + " not provided.");
-            return false;
-        }
-        if (oidParamString.size() != 1) {
-            logger.debug("Found " + oidParamString.size() + " openid headers.");
-            return false;
-        }
-
-        /* Parse the parameters. Do it first to avoid a useless discovery. */
-        ParameterList oidParams = splitParams(oidParamString.get(0));
-        if (oidParams == null) {
-            return false;
-        }
-
-        VerificationResult verification = null;
-        try {
-            verification = manager.verify(RETURN_URL, oidParams, discovered);
-        } catch (MessageException e) {
-            logger.debug("Verification failed: " + e.getMessage());
-            return false;
-        } catch (DiscoveryException e) {
-            logger.debug("Verification discovery exception: " + e.getMessage());
-            return false;
-        } catch (AssociationException e) {
-            logger.debug("Verification assoc exception: " + e.getMessage());
-            return false;
-        }
-
-
-        /* See what could be verified */
-        Identifier verified = verification.getVerifiedId();
-        if (verified == null) {
-            logger.debug("Failed to verify Identity information: " +
-                    verification.getStatusMsg());
-            return false;
-        }
-
-        logger.debug("Verified user: " + verified);
-
-        return true;
-    }
-
-    @Override
-    public boolean isAuthenticated(HttpHeaders headers) {
-        if (!discoveryDone) {
-            discoveryDone = discoverServer();
-        }
-        if (!discoveryDone) {
-            return false;
-        }
-        if (checkOpenIDHeader(headers)) {
-            /** Successfully authenticated. */
-            return true;
-        } else {
-
-            return false;
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/intevation/lada/util/auth/OpenIDFilter.java	Wed Feb 25 16:56:12 2015 +0100
@@ -0,0 +1,222 @@
+/* Copyright (C) 2015 by Bundesamt fuer Strahlenschutz
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU GPL (v>=3) 
+ * and comes with ABSOLUTELY NO WARRANTY! Check out 
+ * the documentation coming with IMIS-Labordaten-Application for details. 
+ */
+
+package de.intevation.lada.util.auth;
+
+import org.apache.log4j.Logger;
+
+import java.util.Map;
+import java.util.List;
+import java.util.LinkedHashMap;
+import java.net.URLDecoder;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpSession;
+
+import org.openid4java.association.AssociationSessionType;
+import org.openid4java.association.AssociationException;
+import org.openid4java.consumer.ConsumerManager;
+import org.openid4java.consumer.ConsumerException;
+import org.openid4java.consumer.InMemoryConsumerAssociationStore;
+import org.openid4java.consumer.InMemoryNonceVerifier;
+import org.openid4java.message.ParameterList;
+import org.openid4java.consumer.VerificationResult;
+import org.openid4java.discovery.DiscoveryInformation;
+import org.openid4java.discovery.Identifier;
+import org.openid4java.discovery.DiscoveryException;
+import org.openid4java.message.MessageException;
+import org.openid4java.message.AuthRequest;
+
+/** ServletFilter used for OpenID authentification. */
+@WebFilter("/*")
+public class OpenIDFilter implements Filter
+{
+    private static Logger logger = Logger.getLogger(OpenIDFilter.class);
+
+    private ConsumerManager manager;
+
+    /* This should be moved into a map <server->discovered>
+     * as we currently only supporting one server this is static. */
+    boolean discoveryDone = false;
+    private DiscoveryInformation discovered;
+    private String authRequestURL;
+
+    /** TODO: get this from config. */
+    /** The name of the header field used to transport OpenID parameters.*/
+    private static final String OID_HEADER_FIELD= "X-OPENID-PARAMS";
+
+    /** The identity provider we accept here. */
+    private static final String IDENTITY_PROVIDER =
+        "http://localhost:8087/account";
+
+    /** This is currently a faked dummy */
+    private static final String RETURN_URL =
+        "http://localhost:8086/consumer-servlet/consumer?is_return=true";
+
+    private boolean discoverServer() {
+        /* Perform discovery on the configured IDENTITY_PROVIDER */
+        List discoveries = null;
+        try {
+            discoveries = manager.discover(IDENTITY_PROVIDER);
+        } catch (DiscoveryException e) {
+            logger.debug("Discovery failed: " + e.getMessage());
+            return false;
+        }
+
+        if (discoveries == null || discoveries.isEmpty()) {
+            logger.error(
+                    "Failed discovery step. OpenID provider unavailable?");
+            return false;
+        }
+
+        /* Add association for the discovered information */
+        discovered = manager.associate(discoveries);
+
+        /* Validate the parameters. */
+        logger.debug("After discovery.");
+        try {
+            AuthRequest authReq = manager.authenticate(discovered, RETURN_URL);
+            authRequestURL = authReq.getDestinationUrl(true);
+            logger.debug("Authenticate with: " + authRequestURL);
+        } catch (MessageException e) {
+            logger.debug("Failed to create the Authentication request: " +
+                    e.getMessage());
+        } catch (ConsumerException e) {
+            logger.debug("Error in consumer manager: " +
+                    e.getMessage());
+        }
+        return true;
+    }
+
+    /** Split up the OpenID response query provided in the header.
+     *
+     * @param responseQuery The query provided in the header field.
+     * @return The query as ParameterList or null on error.
+     */
+    private ParameterList splitParams(String responseQuery) {
+        Map<String, String> queryMap =
+            new LinkedHashMap<String, String>();
+        final String[] pairs = responseQuery.split("&");
+        for (String pair : pairs) {
+            final int idx = pair.indexOf("=");
+            if (idx <= 0) {
+                logger.debug("Invalid query.");
+                return null;
+            }
+            try {
+                final String key = URLDecoder.decode(
+                        pair.substring(0, idx), "UTF-8");
+
+                if (queryMap.containsKey(key)) {
+                    logger.debug("Invalid query. Duplicate key: " + key);
+                    return null;
+                }
+                final String value = URLDecoder.decode(
+                        pair.substring(idx + 1), "UTF-8");
+                queryMap.put(key, value);
+            } catch (java.io.UnsupportedEncodingException e) {
+                logger.error("UTF-8 unkown?!");
+                return null;
+            }
+        }
+        if (queryMap.isEmpty()) {
+            logger.debug("Empty query.");
+            return null;
+        }
+        return new ParameterList(queryMap);
+    }
+
+    private boolean checkOpenIDHeader(ServletRequest req) {
+
+        HttpServletRequest hReq = (HttpServletRequest) req;
+        /* First check if the header is provided at all */
+        String oidParamString = hReq.getHeader(OID_HEADER_FIELD);
+
+        if (oidParamString == null) {
+            logger.debug("Header " + OID_HEADER_FIELD + " not provided.");
+            return false;
+        }
+
+        /* Parse the parameters to a map for openid4j */
+        ParameterList oidParams = splitParams(oidParamString);
+        if (oidParams == null) {
+            return false;
+        }
+
+        /* Verify against the discovered server. */
+        VerificationResult verification = null;
+        try {
+            verification = manager.verify(RETURN_URL, oidParams, discovered);
+        } catch (MessageException e) {
+            logger.debug("Verification failed: " + e.getMessage());
+            return false;
+        } catch (DiscoveryException e) {
+            logger.debug("Verification discovery exception: " + e.getMessage());
+            return false;
+        } catch (AssociationException e) {
+            logger.debug("Verification assoc exception: " + e.getMessage());
+            return false;
+        }
+
+        /* See what could be verified */
+        Identifier verified = verification.getVerifiedId();
+        if (verified == null) {
+            logger.debug("Failed to verify Identity information: " +
+                    verification.getStatusMsg());
+            return false;
+        }
+
+        logger.debug("Verified user: " + verified);
+
+        return true;
+    }
+
+    @Override
+    public void init(FilterConfig config)
+    throws ServletException
+    {
+        manager = new ConsumerManager();
+        /* TODO: Check for alternative configs. */
+        manager.setAssociations(new InMemoryConsumerAssociationStore());
+        manager.setNonceVerifier(new InMemoryNonceVerifier(50000));
+        manager.setMinAssocSessEnc(AssociationSessionType.DH_SHA256);
+        discoveryDone = discoverServer();
+    }
+
+    @Override
+    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
+    throws IOException, ServletException
+    {
+        if (!discoveryDone) {
+            discoveryDone = discoverServer();
+        }
+        if (discoveryDone && checkOpenIDHeader(req)) {
+            /** Successfully authenticated. */
+            chain.doFilter(req, resp);
+        }
+        ((HttpServletResponse) resp).sendError(401, "{\"success\":false,\"message\":\"699\",\"data\":" +
+                "\"" + authRequestURL + "\",\"errors\":{},\"warnings\":{}," +
+                "\"readonly\":false,\"totalCount\":0}");
+    }
+    @Override
+    public void destroy()
+    {
+    }
+};
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)