From d71a87f12afb08371a3f50030f183a89d9e319ca Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Fri, 12 Aug 2016 11:48:05 +0200 Subject: fix a lot of problems which occur with new eIDAS SAML Engine v1.1.0 --- .../moa/id/auth/modules/eidas/Constants.java | 5 + .../MOAeIDASSAMLEngineConfigurationImpl.java | 2 + .../MOAeIDASSAMLInstanceConfigurationImpl.java | 18 +- .../eidas/engine/MOAEidasProtocolProcesser.java | 50 +++ .../eidas/utils/MOAPersonalAttributeList.java | 343 --------------------- .../eidas/utils/MOAeIDASMetadataGenerator.java | 8 + .../auth/modules/eidas/utils/SAMLEngineUtils.java | 4 +- .../moa/id/protocols/eidas/EIDASProtocol.java | 135 +++++--- .../id/protocols/eidas/EidasMetaDataRequest.java | 8 +- .../eidas/eIDASAuthenticationRequest.java | 57 +++- 10 files changed, 220 insertions(+), 410 deletions(-) create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java delete mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java (limited to 'id/server/modules/moa-id-module-eIDAS/src') diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java index b0d27cc32..eb32d1d12 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java @@ -51,6 +51,7 @@ public class Constants { //configuration property keys public static final String CONIG_PROPS_EIDAS_PREFIX="moa.id.protocols.eIDAS"; public static final String CONIG_PROPS_EIDAS_SAMLENGINE="samlengine"; + public static final String CONIG_PROPS_EIDAS_NODE= CONIG_PROPS_EIDAS_PREFIX + ".node"; public static final String CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX=CONIG_PROPS_EIDAS_PREFIX + "." + CONIG_PROPS_EIDAS_SAMLENGINE; public static final String CONIG_PROPS_EIDAS_SAMLENGINE_BASIC_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + ".config.file"; public static final String CONIG_PROPS_EIDAS_SAMLENGINE_SIGN="sign"; @@ -61,6 +62,10 @@ public class Constants { + CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT + ".config.file"; public static final String CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE = CONIG_PROPS_EIDAS_PREFIX + ".metadata.validation.truststore"; + public static final String CONIG_PROPS_EIDAS_NODE_COUNTRYCODE = CONIG_PROPS_EIDAS_NODE + ".countrycode"; + public static final String CONIG_PROPS_EIDAS_NODE_COUNTRY = CONIG_PROPS_EIDAS_NODE + ".country"; + + //timeouts and clock skews public static final long CONFIG_PROPS_SKEWTIME = 2 * 60 * 1000; //2 minutes skew time for response validation public static final int CONFIG_PROPS_METADATA_SOCKED_TIMEOUT = 20 * 1000; //20 seconds metadata socked timeout diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java index 9f6ba4af4..78793d3fc 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java @@ -245,6 +245,8 @@ public class MOAeIDASSAMLEngineConfigurationImpl extends configFile, AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); + Logger.debug("Load eIDAS configuration from file:" + absoluteConfigFile); + File file = new File(new URL(absoluteConfigFile).toURI()); is = new FileInputStream(file); props.loadFromXML(is); diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java index 2d76be206..384d6be0b 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java @@ -22,7 +22,8 @@ */ package at.gv.egovernment.moa.id.auth.modules.eidas.config; -import java.net.MalformedURLException; +import java.io.File; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; @@ -35,6 +36,7 @@ import java.util.Properties; import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.FileUtils; import eu.eidas.samlengineconfig.ConfigurationParameter; import eu.eidas.samlengineconfig.InstanceConfiguration; @@ -85,9 +87,19 @@ public class MOAeIDASSAMLInstanceConfigurationImpl extends AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); URI uri = new URL(absoluteConfigFile).toURI(); - param.setValue(uri.getRawPath().substring(1)); - } catch (ConfigurationException | MalformedURLException | URISyntaxException e) { + File file = new File(uri); + if (file.exists()) + param.setValue(file.getCanonicalPath()); + + else { + Logger.error("eIDAS-configuration fileparameter with key:" + param.getName() + " and path:" + uri.toString() + " NOT exist!"); + param.setValue(null); + + } + + + } catch (ConfigurationException | URISyntaxException | IOException e) { //TODO: make final!!!! e.printStackTrace(); param.setValue(next.getValue()); diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java new file mode 100644 index 000000000..f214efc90 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java @@ -0,0 +1,50 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.engine; + +import eu.eidas.auth.engine.core.eidas.EidasProtocolProcessor; +import eu.eidas.auth.engine.metadata.MetadataFetcherI; +import eu.eidas.auth.engine.metadata.MetadataSignerI; + +/** + * @author tlenz + * + */ +public class MOAEidasProtocolProcesser extends EidasProtocolProcessor { + + private final MetadataFetcherI metadataFetcher; + private final MetadataSignerI metadataSigner; + + /** + * @param metadataFetcher + * @param metadataSigner + */ + public MOAEidasProtocolProcesser(MetadataFetcherI metadataFetcher, MetadataSignerI metadataSigner) { + super(metadataFetcher, metadataSigner); + + this.metadataFetcher = metadataFetcher; + this.metadataSigner = metadataSigner; + + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java deleted file mode 100644 index d559cdba7..000000000 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java +++ /dev/null @@ -1,343 +0,0 @@ -///* -// * Copyright 2014 Federal Chancellery Austria -// * MOA-ID has been developed in a cooperation between BRZ, the Federal -// * Chancellery Austria - ICT staff unit, and Graz University of Technology. -// * -// * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by -// * the European Commission - subsequent versions of the EUPL (the "Licence"); -// * You may not use this work except in compliance with the Licence. -// * You may obtain a copy of the Licence at: -// * http://www.osor.eu/eupl/ -// * -// * Unless required by applicable law or agreed to in writing, software -// * distributed under the Licence is distributed on an "AS IS" basis, -// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// * See the Licence for the specific language governing permissions and -// * limitations under the Licence. -// * -// * This product combines work with different licenses. See the "NOTICE" text -// * file for details on the various modules and licenses. -// * The "NOTICE" text file is part of the distribution. Any derivative works -// * that you distribute must include a readable copy of the "NOTICE" text file. -// */ -//package at.gv.egovernment.moa.id.auth.modules.eidas.utils; -// -//import java.io.IOException; -//import java.io.ObjectInputStream; -//import java.util.ArrayList; -//import java.util.Collections; -//import java.util.HashMap; -//import java.util.Iterator; -//import java.util.List; -//import java.util.Map; -//import java.util.StringTokenizer; -//import java.util.concurrent.ConcurrentHashMap; -// -//import org.apache.commons.lang.StringUtils; -// -//import at.gv.egovernment.moa.logging.Logger; -// -//import eu.eidas.auth.commons.AttributeConstants; -//import eu.eidas.auth.commons.AttributeUtil; -//import eu.eidas.auth.commons.EIDASErrors; -//import eu.eidas.auth.commons.EIDASParameters; -//import eu.eidas.auth.commons.EIDASUtil; -//import eu.eidas.auth.commons.EIDASValues; -//import eu.eidas.auth.commons.IPersonalAttributeList; -//import eu.eidas.auth.commons.PersonalAttribute; -//import eu.eidas.auth.commons.exceptions.InternalErrorEIDASException; -// -///** -// * @author tlenz -// * -// */ -//public final class MOAPersonalAttributeList extends -// ConcurrentHashMap implements IPersonalAttributeList { -// -// /** -// * -// */ -// private static final long serialVersionUID = -4488124133022713089L; -// -// public MOAPersonalAttributeList(IPersonalAttributeList eIDASAttributeList) { -// super(); -// Iterator element = eIDASAttributeList.iterator(); -// while(element.hasNext()) -// add(element.next()); -// -// } -// -// /** -// * Hash with the latest fetched attribute name alias. -// */ -// private Map latestAttrAlias = -// new HashMap(); -// -// /** -// * Hash with mapping number of alias or the attribute name. -// */ -// private Map attrAliasNumber = -// new HashMap(); -// private List insertOrder = new ArrayList(); -// -// /** -// * Obtain the insertOrder Collection -// * -// * @return defensive copy of the collection -// */ -// List getInsertOrder() { -// return Collections.unmodifiableList(this.insertOrder); -// } -// -// /** -// * Default constructor. -// */ -// public MOAPersonalAttributeList() { -// super(); -// -// } -// -// /** -// * Constructor with initial capacity for the PersonalAttributeList size. -// * -// * @param capacity The initial capacity for the PersonalAttributeList. -// */ -// public MOAPersonalAttributeList(final int capacity) { -// super(capacity); -// } -// -// /** -// * {@inheritDoc} -// */ -// public Iterator iterator() { -// return new MOAOrderedAttributeIterator(this); -// } -// -// /** -// * {@inheritDoc} -// */ -// public PersonalAttribute get(final Object key) { -// String attrName = (String) key; -// -// if (this.latestAttrAlias == null) -// this.latestAttrAlias = new HashMap(); -// -// if (this.attrAliasNumber == null) -// this.attrAliasNumber = new HashMap(); -// -// if (this.latestAttrAlias.containsKey(key)) { -// attrName = attrName + this.latestAttrAlias.get(key); -// } else { -// if (this.attrAliasNumber.containsKey(key)) { -// this.latestAttrAlias.put(attrName, this.attrAliasNumber.get(key)); -// } -// } -// return super.get(attrName); -// } -// -// /** -// * {@inheritDoc} -// */ -// public void add(final PersonalAttribute value) { -// if (value != null) { -// this.put(value.getName(), value); -// } -// } -// -// /** -// * {@inheritDoc} -// */ -// public PersonalAttribute put(final String key, final PersonalAttribute val) { -// if (StringUtils.isNotEmpty(key) && val != null) { -// // Validate if attribute name already exists! -// String attrAlias = key; -// if (this.containsKey(attrAlias)) { -// if (this.attrAliasNumber == null) -// this.attrAliasNumber = new HashMap(); -// if (!val.isEmptyValue() && StringUtils.isNumeric(val.getValue().get(0))) { -// final String attrValue = val.getValue().get(0); -// attrAlias = key + attrValue; -// this.attrAliasNumber.put(key, Integer.valueOf(attrValue)); -// } else { -// final PersonalAttribute attr = super.get(key); -// if (!attr.isEmptyValue() -// && StringUtils.isNumeric(attr.getValue().get(0))) { -// attrAlias = key + attr.getValue().get(0); -// super.put(key, (PersonalAttribute) attr); -// this.attrAliasNumber.put(key, null); -// } -// } -// } else { -// if (insertOrder == null) -// insertOrder = new ArrayList(); -// -// insertOrder.add(key); -// } -// return super.put(attrAlias, val); -// } else { -// return null; -// } -// } -// -// @Override -// public PersonalAttribute remove(Object key) { -// insertOrder.remove(key); -// return super.remove(key); -// } -// -// /** -// * {@inheritDoc} -// */ -// public void populate(final String attrList) { -// final StringTokenizer strToken = -// new StringTokenizer(attrList, EIDASValues.ATTRIBUTE_SEP.toString()); -// -// while (strToken.hasMoreTokens()) { -// final PersonalAttribute persAttr = new PersonalAttribute(); -// String[] tuples = -// strToken.nextToken().split(EIDASValues.ATTRIBUTE_TUPLE_SEP.toString(), -// AttributeConstants.NUMBER_TUPLES.intValue()); -// -// // Convert to the new format if needed! -// tuples = convertFormat(tuples); -// -// if (AttributeUtil.hasValidTuples(tuples)) { -// final int attrValueIndex = -// AttributeConstants.ATTR_VALUE_INDEX.intValue(); -// final String tmpAttrValue = -// tuples[attrValueIndex].substring(1, -// tuples[attrValueIndex].length() - 1); -// final String[] vals = -// tmpAttrValue.split(EIDASValues.ATTRIBUTE_VALUE_SEP.toString()); -// -// persAttr.setName(tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()]); -// persAttr.setIsRequired(Boolean -// .valueOf(tuples[AttributeConstants.ATTR_TYPE_INDEX.intValue()])); -// // check if it is a complex value -// if (tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()] -// .equals(EIDASParameters.COMPLEX_ADDRESS_VALUE.toString())) { -// persAttr.setComplexValue(createComplexValue(vals)); -// } else { -// persAttr.setValue(createValues(vals)); -// } -// -// if (tuples.length == AttributeConstants.NUMBER_TUPLES.intValue()) { -// persAttr.setStatus(tuples[AttributeConstants.ATTR_STATUS_INDEX -// .intValue()]); -// } -// this.put(tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()], -// persAttr); -// -// } else { -// Logger.info("BUSINESS EXCEPTION : Invalid personal attribute list tuples"); -// } -// -// } -// } -// -// /** -// * Returns a copy of this IPersonalAttributeList instance. -// * -// * @return The copy of this IPersonalAttributeList. -// */ -// public Object clone() { -// try { -// MOAPersonalAttributeList theClone= (MOAPersonalAttributeList)super.clone(); -// theClone.insertOrder=new ArrayList(insertOrder); -// return theClone; -// -// } catch (CloneNotSupportedException e) { -// throw new InternalErrorEIDASException( -// EIDASUtil.getConfig(EIDASErrors.INTERNAL_ERROR.errorCode()), -// EIDASUtil.getConfig(EIDASErrors.INTERNAL_ERROR.errorMessage()), e); -// } -// } -// -// /** -// * Creates a string in the following format. -// * -// * attrName:attrType:[attrValue1,attrValue2=attrComplexValue]:attrStatus; -// * -// * @return {@inheritDoc} -// */ -// @Override -// public String toString() { -// final StringBuilder strBuilder = new StringBuilder(); -// final Iterator iteratorInsertOrder = insertOrder.iterator(); -// while (iteratorInsertOrder.hasNext()) { -// String key = iteratorInsertOrder.next(); -// final PersonalAttribute attr = get(key); -// strBuilder.append(attr.toString()); -// if (isNumberAlias(key)) { -// strBuilder.append(get(key).toString()); -// } -// } -// return strBuilder.toString(); -// } -// -// /** -// * Validates and creates the attribute's complex values. -// * -// * @param values The complex values. -// * @return The {@link Map} with the complex values. -// * @see Map -// */ -// private Map createComplexValue(final String[] values) { -// final Map complexValue = new HashMap(); -// for (final String val : values) { -// final String[] tVal = val.split("="); -// if (StringUtils.isNotEmpty(val) && tVal.length == 2) { -// complexValue.put(tVal[0], AttributeUtil.unescape(tVal[1])); -// } -// } -// return complexValue; -// } -// -// /** -// * Validates and creates the attribute values. -// * -// * @param vals The attribute values. -// * @return The {@link List} with the attribute values. -// * @see List -// */ -// private List createValues(final String[] vals) { -// final List values = new ArrayList(); -// for (final String val : vals) { -// if (StringUtils.isNotEmpty(val)) { -// values.add(AttributeUtil.unescape(val)); -// } -// } -// return values; -// } -// -// ////////////////// -// /** -// * Converts the attribute tuple (attrName:attrType...) to the new format. -// * -// * @param tuples The attribute tuples to convert. -// * @return The attribute tuples in the new format. -// */ -// private String[] convertFormat(final String[] tuples) { -// final String[] newFormatTuples = -// new String[AttributeConstants.NUMBER_TUPLES.intValue()]; -// if (tuples != null) { -// System.arraycopy(tuples, 0, newFormatTuples, 0, tuples.length); -// -// for (int i = tuples.length; i < newFormatTuples.length; i++) { -// if (i == AttributeConstants.ATTR_VALUE_INDEX.intValue()) { -// newFormatTuples[i] = "[]"; -// } else { -// newFormatTuples[i] = ""; -// } -// } -// } -// return newFormatTuples; -// } -// -// public boolean isNumberAlias(String key) { -// return this.attrAliasNumber.containsKey(key); -// } -// -// -// -//} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java index c614e6490..09c3dff38 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java @@ -609,5 +609,13 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator { attributes.add(a); } } + + public MetadataConfigParams getConfigParams() { + return params; + } + + public void setConfigParams(MetadataConfigParams params) { + this.params = params; + } } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java index cdae92e58..b95d4359f 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java @@ -28,6 +28,7 @@ import java.util.Map; import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; import at.gv.egovernment.moa.id.auth.modules.eidas.config.MOAIDCertificateManagerConfigurationImpl; import at.gv.egovernment.moa.id.auth.modules.eidas.config.MOASWSigner; +import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAEidasProtocolProcesser; import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASMetadataProviderDecorator; import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; @@ -35,7 +36,6 @@ import at.gv.egovernment.moa.logging.Logger; import eu.eidas.auth.commons.attribute.AttributeDefinition; import eu.eidas.auth.engine.ProtocolEngineI; import eu.eidas.auth.engine.SamlEngineSystemClock; -import eu.eidas.auth.engine.core.eidas.EidasProtocolProcessor; import eu.eidas.auth.engine.metadata.MetadataFetcherI; import eu.eidas.auth.engine.metadata.MetadataSignerI; import eu.eidas.engine.exceptions.EIDASSAMLEngineException; @@ -70,7 +70,7 @@ public class SAMLEngineUtils { ProtocolEngineI engine = MOAProtocolEngineFactory.createProtocolEngine( Constants.eIDAS_SAML_ENGINE_NAME, configManager, - new EidasProtocolProcessor(metadataFetcher, metadataSigner), + new MOAEidasProtocolProcesser(metadataFetcher, metadataSigner), new SamlEngineSystemClock()); //build a map with all actually supported attributes diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java index cf9414a3b..cb91d5fa3 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java @@ -34,6 +34,7 @@ import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.opensaml.saml2.core.StatusCode; import org.opensaml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml2.metadata.EntityDescriptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; @@ -49,6 +50,7 @@ import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASAuthnRequestP import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASAuthnRequestValidationException; import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASException; import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; import at.gv.egovernment.moa.id.commons.api.IRequest; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; @@ -59,6 +61,8 @@ import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.auth.commons.EidasStringUtil; import eu.eidas.auth.commons.protocol.IAuthenticationRequest; import eu.eidas.auth.commons.protocol.IResponseMessage; +import eu.eidas.auth.commons.protocol.eidas.IEidasAuthenticationRequest; +import eu.eidas.auth.commons.protocol.eidas.impl.EidasAuthenticationRequest; import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse; import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse.Builder; import eu.eidas.auth.engine.ProtocolEngineI; @@ -74,7 +78,7 @@ import eu.eidas.engine.exceptions.EIDASSAMLEngineException; public class EIDASProtocol extends AbstractAuthProtocolModulController { public static final String NAME = EIDASProtocol.class.getName(); - public static final String PATH = "eidas"; + public static final String PATH = "eidas"; @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider; @@ -169,7 +173,7 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { String base64SamlToken = request.getParameter("SAMLRequest"); if (MiscUtil.isEmpty(base64SamlToken)) { Logger.warn("No eIDAS SAMLRequest found in http request."); - throw new MOAIDException("HTTP request includes no eIDAS SAML-Request element.", null); + throw new MOAIDException("eIDAS.06", new Object[]{"HTTP request includes no eIDAS SAML-Request element."}); } try { @@ -178,34 +182,29 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { //get eIDAS SAML-engine ProtocolEngineI engine = SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); - - //TODO: change to configurable COUNTRY-CODE - String cititzenCountryCode = "AT"; - //validate SAML token - IAuthenticationRequest samlReq = engine.unmarshallRequestAndValidate(decSamlToken, cititzenCountryCode ); - - // - memorize remote ip - pendingReq.setRemoteAddress(request.getRemoteAddr()); - - // - memorize relaystate - String relayState = request.getParameter("RelayState"); - pendingReq.setRemoteRelayState(relayState); - - // - memorize country code of target country - pendingReq.setGenericDataToSession( - RequestImpl.eIDAS_GENERIC_REQ_DATA_COUNTRY, samlReq.getOriginCountryCode()); - //TODO: store level of assurance + String cititzenCountryCode = + authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, + MOAIDAuthConstants.COUNTRYCODE_AUSTRIA); - // - memorize requested attributes - pendingReq.setEidasRequestedAttributes(samlReq.getRequestedAttributes()); + //**************************************** + //***** validate eIDAS request ********* + //**************************************** + //validate SAML token + IAuthenticationRequest samlReq = engine.unmarshallRequestAndValidate(decSamlToken, cititzenCountryCode ); - // - memorize whole request - pendingReq.setEidasRequest(samlReq); - + //validate internal JAVA class type + if (!(samlReq instanceof IEidasAuthenticationRequest)) { + Logger.error("eIDAS AuthnRequst from node:" + samlReq.getIssuer() + + " is NOT from Type:" + IEidasAuthenticationRequest.class.getName()); + throw new MOAIDException("eIDAS.06", new Object[]{"eIDAS AuthnRequest maps to an wrong internal Type."}); + + } + IEidasAuthenticationRequest eIDASSamlReq = (IEidasAuthenticationRequest) samlReq; + //validate Destination against MOA-ID-Auth configuration - String reqDestination = samlReq.getDestination(); + String reqDestination = eIDASSamlReq.getDestination(); if (MiscUtil.isEmpty(reqDestination) || !reqDestination.startsWith(pendingReq.getAuthURL())) { Logger.info("eIDAS AuthnRequest contains a not valid 'Destination' attribute"); @@ -213,13 +212,16 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { new Object[]{"eIDAS AuthnRequest contains a not valid 'Destination' attribute"}); } - + //validate AssertionConsumerServiceURL against metadata - String reqAssertionConsumerServiceURL = samlReq.getAssertionConsumerServiceURL(); + EntityDescriptor eIDASNodeEntityDesc = new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider) + .getEntityDescriptor(eIDASSamlReq.getIssuer(), SAMLEngineUtils.getMetadataSigner()); + + String reqAssertionConsumerServiceURL = eIDASSamlReq.getAssertionConsumerServiceURL(); if (MiscUtil.isNotEmpty(reqAssertionConsumerServiceURL)) { - boolean isValid = false; - List allowedAssertionConsumerUrl = new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider) - .getSPSSODescriptor(samlReq.getIssuer()).getAssertionConsumerServices(); + boolean isValid = false; + List allowedAssertionConsumerUrl = + MetadataUtil.getSPSSODescriptor(eIDASNodeEntityDesc).getAssertionConsumerServices(); for (AssertionConsumerService el : allowedAssertionConsumerUrl) { if (reqAssertionConsumerServiceURL.equals(el.getLocation())) @@ -229,13 +231,59 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { if (!isValid) { Logger.info("eIDAS AuthnRequest contains a not valid 'AssertionConsumerServiceURL' attribute"); - throw new EIDASAuthnRequestValidationException("stork.01", + throw new EIDASAuthnRequestValidationException("eIDAS.12", new Object[]{"eIDAS AuthnRequest contains a not valid 'AssertionConsumerServiceURL' attribute"}); } - } + } else { + /*TODO: eIDAS SAMLEngine 1.1.0 does not validate and set AssertionConsumerServiceURL in a correct form + * + * Actually, this step is required because EidasProtocolProcesser.class only use the AssertionConsumerServiceURL + * from AuthnRequest to set the 'Destination' attribute in eIDAS Response. However, the AssertionConsumerServiceURL + * could be empty in Request, which break the Response building process. + */ + String assertionConsumerServiceURL = MetadataUtil.getAssertionConsumerUrlFromMetadata( + SAMLEngineUtils.getMetadataFetcher(), SAMLEngineUtils.getMetadataSigner(), eIDASSamlReq); + if (MiscUtil.isEmpty(assertionConsumerServiceURL)) { + Logger.error("eIDAS metadata for node:" + eIDASSamlReq.getIssuer() + + " contains NO 'AssertionConsumerServiceURL' element!"); + throw new EIDASSAMLEngineException("eIDAS metadata for node:" + eIDASSamlReq.getIssuer() + + " contains NO 'AssertionConsumerServiceURL' element!"); + + } + + EidasAuthenticationRequest.Builder test = EidasAuthenticationRequest.builder(eIDASSamlReq); + test.assertionConsumerServiceURL(assertionConsumerServiceURL); + eIDASSamlReq = test.build(); + + } + + + + //************************************************* + //***** store eIDAS request information ********* + //************************************************* + // - memorize remote ip + pendingReq.setRemoteAddress(request.getRemoteAddr()); + + // - memorize relaystate + String relayState = request.getParameter("RelayState"); + pendingReq.setRemoteRelayState(relayState); + + // - memorize country code of target country + pendingReq.setGenericDataToSession( + RequestImpl.eIDAS_GENERIC_REQ_DATA_COUNTRY, samlReq.getOriginCountryCode()); + //store level of assurance + pendingReq.setGenericDataToSession(RequestImpl.eIDAS_GENERIC_REQ_DATA_LEVELOFASSURENCE, + eIDASSamlReq.getEidasLevelOfAssurance().stringValue()); + // - memorize requested attributes + pendingReq.setEidasRequestedAttributes(eIDASSamlReq.getRequestedAttributes()); + + // - memorize whole request + pendingReq.setEidasRequest(eIDASSamlReq); + // - memorize OA url pendingReq.setOAURL(samlReq.getIssuer()); @@ -245,16 +293,19 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { throw new EIDASAuthnRequestProcessingException("eIDAS.08", new Object[]{pendingReq.getOAURL()}); pendingReq.setOnlineApplicationConfiguration(oaConfig); - - //TODO: is not supported any more ?!? -// String spType = samlReq.getSPType(); -// if (MiscUtil.isEmpty(spType)) { -// Logger.info("Load SPType from metadata ... IS NOT IMPLEMENTED YET!!!"); -// //TODO: maybe implement this if required -// -// } -// -// Logger.debug("eIDAS request has SPType:" + spType); + + // - memorize service-provider type from eIDAS request + String spType = null; + if (eIDASSamlReq.getSpType() != null) + spType = eIDASSamlReq.getSpType().getValue(); + + if (MiscUtil.isEmpty(spType)) + spType = MetadataUtil.getSPTypeFromMetadata(eIDASNodeEntityDesc); + + if (MiscUtil.isEmpty(spType)) + Logger.debug("eIDAS request has SPType:" + spType); + else + Logger.info("eIDAS request and eIDAS metadata contains NO 'SPType' element."); } catch (MOAIDException e) { Logger.info("eIDAS AuthnRequest preProcessing FAILED. Msg:" + e.getMessage()); diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java index a93dff3b3..dcce442a0 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java @@ -31,7 +31,9 @@ import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAeIDASMetadataGenerator; import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; import at.gv.egovernment.moa.id.commons.api.IRequest; import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; @@ -43,7 +45,6 @@ import at.gv.egovernment.moa.logging.Logger; import eu.eidas.auth.engine.ProtocolEngineI; import eu.eidas.auth.engine.metadata.Contact; import eu.eidas.auth.engine.metadata.MetadataConfigParams; -import eu.eidas.auth.engine.metadata.MetadataGenerator; import eu.eidas.engine.exceptions.EIDASSAMLEngineException; @@ -54,6 +55,7 @@ import eu.eidas.engine.exceptions.EIDASSAMLEngineException; public class EidasMetaDataRequest implements IAction { @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider; + @Autowired(required=true) AuthConfiguration authConfig; /* (non-Javadoc) * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.data.IAuthData) @@ -110,7 +112,7 @@ public class EidasMetaDataRequest implements IAction { ProtocolEngineI engine = SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); - MetadataGenerator generator = new MetadataGenerator(); + MOAeIDASMetadataGenerator generator = new MOAeIDASMetadataGenerator(); MetadataConfigParams mcp=new MetadataConfigParams(); generator.setConfigParams(mcp); generator.initialize(engine); @@ -158,7 +160,7 @@ public class EidasMetaDataRequest implements IAction { if (pvpOrganisation != null) { mcp.setNodeUrl(pvpOrganisation.getURLs().get(0).getURL().getLocalString()); - mcp.setCountryName("Austria"); + mcp.setCountryName(authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRY, "Austria")); technicalContact.setCompany(pvpOrganisation.getDisplayNames().get(0).getName().getLocalString()); } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java index 9e29c01f3..168cb42d9 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java @@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; +import org.opensaml.saml2.core.StatusCode; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; @@ -50,6 +51,7 @@ import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.auth.commons.EidasStringUtil; import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder; import eu.eidas.auth.commons.attribute.AttributeValue; import eu.eidas.auth.commons.attribute.AttributeValueMarshaller; import eu.eidas.auth.commons.attribute.AttributeValueMarshallingException; @@ -89,36 +91,48 @@ public class eIDASAuthenticationRequest implements IAction { for(AttributeDefinition attr : reqAttributeList.getDefinitions()) { String newValue = ""; - + boolean isUniqueID = false; // TODO make use of proper builder + switch(attr.getFriendlyName()) { - case Constants.eIDAS_ATTR_DATEOFBIRTH: newValue = new SimpleDateFormat("YYYY-MM-dd").format(authData.getDateOfBirth()); break; - case Constants.eIDAS_ATTR_CURRENTFAMILYNAME: newValue = authData.getFamilyName();break; - case Constants.eIDAS_ATTR_CURRENTGIVENNAME: newValue = authData.getGivenName();break; - case Constants.eIDAS_ATTR_PERSONALIDENTIFIER: newValue = authData.getBPK(); break; + case Constants.eIDAS_ATTR_DATEOFBIRTH: + newValue = new SimpleDateFormat("YYYY-MM-dd").format(authData.getDateOfBirth()); + break; + case Constants.eIDAS_ATTR_CURRENTFAMILYNAME: + newValue = authData.getFamilyName(); + break; + case Constants.eIDAS_ATTR_CURRENTGIVENNAME: + newValue = authData.getGivenName(); + break; + case Constants.eIDAS_ATTR_PERSONALIDENTIFIER: + newValue = authData.getBPK(); + isUniqueID = true; + break; } - + if(MiscUtil.isEmpty(newValue)) { -// current.getValue().setStatus(EIDASStatusCode.STATUS_NOT_AVAILABLE.toString()); Logger.info("eIDAS Attr:" + attr.getNameUri() + " is not available."); } else { - AttributeValueMarshaller attributeValueMarshaller = attr.getAttributeValueMarshaller(); - ImmutableSet.Builder> builder = ImmutableSet.builder(); + Builder attrBuilder = AttributeDefinition.builder(attr); + attrBuilder.uniqueIdentifier(isUniqueID); + AttributeDefinition returnAttr = attrBuilder.build(); + AttributeValueMarshaller attributeValueMarshaller = returnAttr.getAttributeValueMarshaller(); + ImmutableSet.Builder> builder = ImmutableSet.builder(); + AttributeValue attributeValue = null; try { attributeValue = attributeValueMarshaller.unmarshal(newValue, false); + builder.add(attributeValue); } catch (AttributeValueMarshallingException e) { throw new IllegalStateException(e); } - - //TODO: check for 'isAvailable flag'! - attrMapBuilder.put((AttributeDefinition)attr, (ImmutableSet) builder.build()); + attrMapBuilder.put((AttributeDefinition)returnAttr, (ImmutableSet) builder.build()); } @@ -141,10 +155,16 @@ public class eIDASAuthenticationRequest implements IAction { //add attributes responseBuilder.attributes(attrMapBuilder.build()); + //set success statuscode + responseBuilder.statusCode(StatusCode.SUCCESS_URI); + + + //build response AuthenticationResponse response = responseBuilder.build(); String token = null; + IResponseMessage eIDASRespMsg = null; try { ProtocolEngineI engine = at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); @@ -152,9 +172,9 @@ public class eIDASAuthenticationRequest implements IAction { // but we need to set the appropriate request issuer //engine.setRequestIssuer(eidasRequest.getEidasRequest().getIssuer()); - IResponseMessage eIDASRespMsg = engine.generateResponseMessage(eidasRequest.getEidasRequest(), + eIDASRespMsg = engine.generateResponseMessage(eidasRequest.getEidasRequest(), response, true, eidasRequest.getRemoteAddress()); - + // if(null == eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()) { // String assertionConsumerUrl = MetadataUtil.getAssertionUrlFromMetadata( // new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider), @@ -169,8 +189,9 @@ public class eIDASAuthenticationRequest implements IAction { token = EidasStringUtil.encodeToBase64(eIDASRespMsg.getMessageBytes()); - } catch(Exception e) { - e.printStackTrace(); + } catch(Exception e) { + Logger.error("eIDAS Response encoding error." , e); + throw new MOAIDException("eIDAS.13", new Object[]{e.getMessage()}, e); } @@ -202,7 +223,9 @@ public class eIDASAuthenticationRequest implements IAction { httpResp.setContentType(MediaType.TEXT_HTML.getType()); } catch (Exception e) { - Logger.error("Velocity error: " + e.getMessage()); + Logger.error("Velocity error: " + e.getMessage()); + throw new MOAIDException("eIDAS.13", new Object[]{e.getMessage()}, e); + } return null; -- cgit v1.2.3