[Lada-commits] [PATCH] First non-functional implementation of openid verification
Wald Commits
scm-commit at wald.intevation.org
Wed Feb 25 16:04:16 CET 2015
# HG changeset patch
# User Andre Heinecke <andre.heinecke at intevation.de>
# Date 1424876615 -3600
# Branch openid
# Node ID 04e254571b8a0bb147a66204fad92867b8038279
# Parent 56a2d43b4af506b10b00ba461d1ffff9aba0d4f3
First non-functional implementation of openid verification
Uses the openid4j package to extract openid information
provided by the client as a HTTP Header.
Currently the statelessness of the services prevents the
exchange of discovery information between client and server.
It is only useful for evaluation and testing.
diff -r 56a2d43b4af5 -r 04e254571b8a pom.xml
--- a/pom.xml Thu Feb 19 15:21:44 2015 +0100
+++ b/pom.xml Wed Feb 25 16:03:35 2015 +0100
@@ -139,6 +139,13 @@
<version>3.0.10.Final</version>
<scope>test</scope>
</dependency>
+
+ <!-- OpenID -->
+ <dependency>
+ <groupId>org.openid4java</groupId>
+ <artifactId>openid4java</artifactId>
+ <version>0.9.7</version>
+ </dependency>
</dependencies>
<profiles>
diff -r 56a2d43b4af5 -r 04e254571b8a src/main/java/de/intevation/lada/rest/ProbeService.java
--- a/src/main/java/de/intevation/lada/rest/ProbeService.java Thu Feb 19 15:21:44 2015 +0100
+++ b/src/main/java/de/intevation/lada/rest/ProbeService.java Wed Feb 25 16:03:35 2015 +0100
@@ -67,7 +67,7 @@
/* The authentication module.*/
@Inject
- @AuthenticationConfig(type=AuthenticationType.NONE)
+ @AuthenticationConfig(type=AuthenticationType.OPENID)
private Authentication authentication;
/* The authorization module.*/
diff -r 56a2d43b4af5 -r 04e254571b8a src/main/java/de/intevation/lada/util/auth/OpenIDAuthentication.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/intevation/lada/util/auth/OpenIDAuthentication.java Wed Feb 25 16:03:35 2015 +0100
@@ -0,0 +1,206 @@
+/* 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;
+ }
+ }
+}
More information about the Lada-commits
mailing list