aboutsummaryrefslogtreecommitdiff
path: root/id/server
diff options
context:
space:
mode:
Diffstat (limited to 'id/server')
-rw-r--r--id/server/data/deploy/conf/moa-id/eIDAS/EncryptModule.xml24
-rw-r--r--id/server/data/deploy/conf/moa-id/eIDAS/SignModule.xml37
-rw-r--r--id/server/doc/handbook/additional/additional.html15
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java25
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/BPKBuilder.java2
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java15
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestImpl.java2
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MOASPMetadataSignatureFilter.java114
-rw-r--r--id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties2
-rw-r--r--id/server/idserverlib/src/main/resources/resources/properties/protocol_response_statuscodes_de.properties2
-rw-r--r--id/server/idserverlib/src/main/resources/resources/templates/pvp_postbinding_template.html10
-rw-r--r--id/server/idserverlib/src/main/resources/resources/templates/saml2-post-binding-moa.vm38
-rw-r--r--id/server/idserverlib/src/main/resources/resources/templates/stork2_consent.html438
-rw-r--r--id/server/idserverlib/src/main/resources/resources/templates/stork2_postbinding_template.html42
-rw-r--r--id/server/moa-id-commons/pom.xml7
-rw-r--r--id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/MOAIDConstants.java2
-rw-r--r--id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/data/CPEPS.java12
-rw-r--r--id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/config/ConfigurationMigrationUtils.java6
-rw-r--r--id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/util/Constants.java2
-rw-r--r--id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/builder/GUIFormBuilderImpl.java3
-rw-r--r--id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/builder/ServiceProviderSpecificGUIFormBuilderConfiguration.java8
-rw-r--r--id/server/moa-id-jaxb_classes/pom.xml14
-rw-r--r--id/server/modules/moa-id-module-eIDAS/pom.xml16
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java18
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java479
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java8
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java68
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java61
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java14
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java17
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java12
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java33
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java6
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeProcessingUtils.java75
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java53
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java16
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java53
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/validator/eIDASResponseValidator.java130
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm2
39 files changed, 1162 insertions, 719 deletions
diff --git a/id/server/data/deploy/conf/moa-id/eIDAS/EncryptModule.xml b/id/server/data/deploy/conf/moa-id/eIDAS/EncryptModule.xml
index 9fef4fa2e..46052053a 100644
--- a/id/server/data/deploy/conf/moa-id/eIDAS/EncryptModule.xml
+++ b/id/server/data/deploy/conf/moa-id/eIDAS/EncryptModule.xml
@@ -3,14 +3,32 @@
<properties>
<comment>SWModule encrypt with JKS.</comment>
- <entry key="keystorePath">keys/eidasKeyStore.jks</entry>
+
+ <entry key="check_certificate_validity_period">false</entry>
+ <entry key="disallow_self_signed_certificate">false</entry>
+ <entry key="response.encryption.mandatory">false</entry>
+
+ <!-- Data Encryption algorithm -->
+ <entry key="data.encryption.algorithm">http://www.w3.org/2009/xmlenc11#aes256-gcm</entry>
+
+ <!-- Decryption algorithm Whitelist-->
+ <entry key="encryption.algorithm.whitelist">
+ http://www.w3.org/2009/xmlenc11#aes128-gcm;
+ http://www.w3.org/2009/xmlenc11#aes256-gcm;
+ http://www.w3.org/2009/xmlenc11#aes192-gcm
+ </entry>
+
+ <!-- Key Encryption algorithm -->
+ <entry key="key.encryption.algorithm">http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p</entry>
+
+ <entry key="keyStorePath">keys/eidasKeyStore.jks</entry>
+ <entry key="keyStoreType">JKS</entry>
<entry key="keyStorePassword">local-demo</entry>
<entry key="keyPassword">local-demo</entry>
<!-- Management of the encryption activation -->
<entry key="encryptionActivation">eIDAS/encryptionConf.xml</entry>
-
<entry key="responseToPointIssuer.BE">CN=local-demo-cert, OU=DIGIT, O=European Comission, L=Brussels, ST=Belgium,C=BE</entry>
<entry key="responseToPointSerialNumber.BE">54C8F779</entry>
@@ -18,5 +36,5 @@
<entry key="responseDecryptionIssuer">CN=local-demo-cert, OU=DIGIT, O=European Comission, L=Brussels, ST=Belgium, C=BE</entry>
<entry key="serialNumber">54C8F779</entry>
- <entry key="keystoreType">JKS</entry>
+
</properties> \ No newline at end of file
diff --git a/id/server/data/deploy/conf/moa-id/eIDAS/SignModule.xml b/id/server/data/deploy/conf/moa-id/eIDAS/SignModule.xml
index 745580428..bf7215cb5 100644
--- a/id/server/data/deploy/conf/moa-id/eIDAS/SignModule.xml
+++ b/id/server/data/deploy/conf/moa-id/eIDAS/SignModule.xml
@@ -3,17 +3,46 @@
<properties>
<comment>SWModule sign with JKS.</comment>
- <entry key="keystorePath">keys/eidasKeyStore_Service_CB.jks</entry>
+ <entry key="check_certificate_validity_period">false</entry>
+ <entry key="disallow_self_signed_certificate">false</entry>
+
+ <!-- signing Algorithm SHA_512(default),SHA_384,SHA_256 -->
+ <!-- http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 -->
+ <!-- http://www.w3.org/2001/04/xmldsig-more#rsa-sha384 -->
+ <!-- http://www.w3.org/2001/04/xmldsig-more#rsa-sha512 -->
+ <entry key="signature.algorithm">http://www.w3.org/2001/04/xmldsig-more#rsa-sha512</entry>
+
+ <!-- List of incoming Signature algorithms white list separated by ; (default all) -->
+ <entry key="signature.algorithm.whitelist">
+ http://www.w3.org/2001/04/xmldsig-more#rsa-sha256;
+ http://www.w3.org/2001/04/xmldsig-more#rsa-sha384;
+ http://www.w3.org/2001/04/xmldsig-more#rsa-sha512;
+ http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160;
+ http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256;
+ http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384;
+ http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512;
+ http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1;
+ http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-mgf1
+ </entry>
+
+ <!-- signing response assertion true/false (default false) -->
+ <entry key="response.sign.assertions">true</entry>
+
+ <!--AuthnRequest / Assertion signing keyStore-->
+ <entry key="keyStorePath">keys/eidasKeyStore_Service_CB.jks</entry>
+ <entry key="keyStoreType">JKS</entry>
<entry key="keyStorePassword">local-demo</entry>
<entry key="keyPassword">local-demo</entry>
<entry key="issuer">CN=cpeps-cb-demo-certificate, OU=STORK, O=CPEPS, L=EU, ST=EU, C=CB</entry>
<entry key="serialNumber">54C8F839</entry>
- <entry key="keystoreType">JKS</entry>
- <entry key="metadata.keystorePath">keys/eidasKeyStore_METADATA.jks</entry>
+
+ <!--Metadata signing keystore-->
+ <entry key="metadata.keyStorePath">keys/eidasKeyStore_METADATA.jks</entry>
+ <entry key="metadata.keyStoreType">JKS</entry>
<entry key="metadata.keyStorePassword">local-demo</entry>
<entry key="metadata.keyPassword">local-demo</entry>
<entry key="metadata.issuer">CN=metadata, OU=DIGIT, O=EC, L=Brussels, ST=EU, C=BE</entry>
<entry key="metadata.serialNumber">561BC0C8</entry>
- <entry key="metadata.keystoreType">JKS</entry>
+
</properties>
diff --git a/id/server/doc/handbook/additional/additional.html b/id/server/doc/handbook/additional/additional.html
index ec57a74c6..9e3cdf11e 100644
--- a/id/server/doc/handbook/additional/additional.html
+++ b/id/server/doc/handbook/additional/additional.html
@@ -361,6 +361,21 @@
<td width="1127" valign="top"><p>SAML1 StartAuthentication Request</p></td>
</tr>
<tr>
+ <td valign="top">3400</td>
+ <td valign="top">&nbsp;</td>
+ <td valign="top">eIDAS Metadata Request</td>
+ </tr>
+ <tr>
+ <td valign="top">3401</td>
+ <td valign="top">Request ID</td>
+ <td valign="top">Eingehender eIDAS Authentication Request</td>
+ </tr>
+ <tr>
+ <td valign="top">3402</td>
+ <td valign="top">Response ID</td>
+ <td valign="top">eIDAS Authentication Response erstellt</td>
+ </tr>
+ <tr>
<td width="165" valign="top"><p align="center">4000</p></td>
<td width="312" valign="top"><p align="left">&nbsp;</p></td>
<td width="1127" valign="top"><p>Identifizierungs- und Authentifizierungsprozess wurde gestartet</p></td>
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java
index 3264fc3bd..cad3354f5 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java
@@ -71,7 +71,6 @@ import at.gv.egovernment.moa.id.data.AuthenticationRoleFactory;
import at.gv.egovernment.moa.id.data.IAuthData;
import at.gv.egovernment.moa.id.data.MISMandate;
import at.gv.egovernment.moa.id.data.Pair;
-import at.gv.egovernment.moa.id.moduls.RequestImpl;
import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration;
import at.gv.egovernment.moa.id.protocols.pvp2x.builder.AttributQueryBuilder;
@@ -1105,16 +1104,20 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants {
String baseID = authData.getIdentificationValue();
String baseIDType = authData.getIdentificationType();
-
- String eIDASOutboundCountry = pendingReq.getGenericData(RequestImpl.eIDAS_GENERIC_REQ_DATA_COUNTRY, String.class);
-
- //TODO: maybe find a better solution
- String cititzenCountryCode =
- authConfig.getBasicMOAIDConfiguration("moa.id.protocols.eIDAS.node.countrycode",
- MOAIDAuthConstants.COUNTRYCODE_AUSTRIA);
-
- if (Constants.URN_PREFIX_BASEID.equals(baseIDType)) {
- if (MiscUtil.isNotEmpty(eIDASOutboundCountry) && !cititzenCountryCode.equals(eIDASOutboundCountry)) {
+
+ if (Constants.URN_PREFIX_BASEID.equals(baseIDType)) {
+ //Calculate eIDAS identifier
+ if (oaParam.getBusinessService() &&
+ oaParam.getIdentityLinkDomainIdentifier().startsWith(Constants.URN_PREFIX_EIDAS)) {
+ String[] splittedTarget = oaParam.getIdentityLinkDomainIdentifier().split("\\+");
+ String cititzenCountryCode = splittedTarget[1];
+ String eIDASOutboundCountry = splittedTarget[2];
+
+ if (cititzenCountryCode.equalsIgnoreCase(eIDASOutboundCountry)) {
+ Logger.warn("Suspect configuration FOUND!!! CitizenCountry equals DestinationCountry");
+
+ }
+
Pair<String, String> eIDASID = new BPKBuilder().buildeIDASIdentifer(baseIDType, baseID,
cititzenCountryCode, eIDASOutboundCountry);
Logger.debug("Authenticate user with bPK:" + eIDASID.getFirst() + " Type:" + eIDASID.getSecond());
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/BPKBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/BPKBuilder.java
index 9e4e36fec..32ac8ad68 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/BPKBuilder.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/BPKBuilder.java
@@ -238,7 +238,7 @@ public class BPKBuilder {
Logger.debug("Building eIDAS identification from: " + sourceCountry+"/"+destinationCountry+"/" + "[identValue]");
String eIdentifier = sourceCountry + "/" + destinationCountry + "/" + bPK;
- return Pair.newInstance(eIdentifier, baseIDType);
+ return Pair.newInstance(eIdentifier, bPKType);
}
private String calculatebPKwbPK(String basisbegriff) throws BuildException {
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java
index 8f6dff849..b85938bb7 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java
@@ -83,11 +83,20 @@ public class STORKConfig implements IStorkConfig {
if (MiscUtil.isNotEmpty(storkCPEPSProps.get(listCounter + "." + MOAIDConfigurationConstants.GENERAL_AUTH_STORK_CPEPS_LIST_COUNTRY))) {
try {
+
+ //Assertion encryption is enabled by default
+ boolean enableAssertionEncryption = true;
+ String enableAssertionEncryptionString = storkCPEPSProps.get(listCounter + "." + MOAIDConfigurationConstants.GENERAL_AUTH_STORK_CPEPS_LIST_SUPPORT_XMLDSIG);
+ if (MiscUtil.isNotEmpty(enableAssertionEncryptionString)) {
+ enableAssertionEncryption = Boolean.parseBoolean(enableAssertionEncryptionString);
+
+ }
+
CPEPS moacpep =
new CPEPS(storkCPEPSProps.get(listCounter + "." + MOAIDConfigurationConstants.GENERAL_AUTH_STORK_CPEPS_LIST_COUNTRY),
new URL(storkCPEPSProps.get(listCounter + "." + MOAIDConfigurationConstants.GENERAL_AUTH_STORK_CPEPS_LIST_URL)),
- Boolean.valueOf(storkCPEPSProps.get(listCounter + "." + MOAIDConfigurationConstants.GENERAL_AUTH_STORK_CPEPS_LIST_SUPPORT_XMLDSIG)));
- cpepsMap.put(moacpep.getCountryCode(), moacpep);
+ enableAssertionEncryption);
+ cpepsMap.put(moacpep.getFullCountryCode(), moacpep);
} catch (MalformedURLException e) {
Logger.warn("CPEPS URL " +
@@ -158,7 +167,7 @@ public class STORKConfig implements IStorkConfig {
if (StringUtils.isEmpty(ccc) || this.cpepsMap.isEmpty())
return false;
- if (this.cpepsMap.containsKey(ccc.toUpperCase()))
+ if (this.cpepsMap.containsKey(ccc))
return true;
else
return false;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestImpl.java
index b612352c6..b87574d52 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestImpl.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestImpl.java
@@ -61,7 +61,7 @@ public abstract class RequestImpl implements IRequest, Serializable{
public static final String DATAID_REQUESTER_IP_ADDRESS = "requesterIP";
- public static final String eIDAS_GENERIC_REQ_DATA_COUNTRY = "country";
+// public static final String eIDAS_GENERIC_REQ_DATA_COUNTRY = "country";
public static final String eIDAS_GENERIC_REQ_DATA_LEVELOFASSURENCE = "eIDAS_LoA";
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MOASPMetadataSignatureFilter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MOASPMetadataSignatureFilter.java
index b6fed5934..16b179d89 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MOASPMetadataSignatureFilter.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MOASPMetadataSignatureFilter.java
@@ -27,6 +27,7 @@ import java.io.IOException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;
+import org.opensaml.saml2.metadata.EntitiesDescriptor;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.provider.FilterException;
import org.opensaml.saml2.metadata.provider.MetadataFilter;
@@ -37,6 +38,7 @@ import at.gv.egovernment.moa.id.commons.api.data.IVerifiyXMLSignatureResponse;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.MiscUtil;
/**
* @author tlenz
@@ -61,67 +63,75 @@ public class MOASPMetadataSignatureFilter implements MetadataFilter {
@Override
public void doFilter(XMLObject metadata) throws FilterException {
if (metadata instanceof EntityDescriptor) {
- if (((EntityDescriptor) metadata).isSigned()) {
- EntityDescriptor entityDes = (EntityDescriptor) metadata;
- //check signature;
- try {
- byte[] serialized = DOMUtils.serializeNode(metadata.getDOM(), "UTF-8");
-
-// Transformer transformer = TransformerFactory.newInstance()
-// .newTransformer();
-// StringWriter sw = new StringWriter();
-// StreamResult sr = new StreamResult(sw);
-// DOMSource source = new DOMSource(metadata.getDOM());
-// transformer.transform(source, sr);
-// sw.close();
-// String metadataXML = sw.toString();
-
- SignatureVerificationUtils sigVerify =
- new SignatureVerificationUtils();
- IVerifiyXMLSignatureResponse result = sigVerify.verify(
- serialized, trustProfileID);
-
- //check signature-verification result
- if (result.getSignatureCheckCode() != 0) {
- Logger.warn("Metadata signature-verification FAILED!"
- + " Metadata: " + entityDes.getEntityID()
- + " StatusCode:" + result.getSignatureCheckCode());
- throw new FilterException("Metadata signature-verification FAILED!"
- + " Metadata: " + entityDes.getEntityID()
- + " StatusCode:" + result.getSignatureCheckCode());
+ checkSignature(metadata, ((EntityDescriptor)metadata).getEntityID());
- }
-
- if (result.getCertificateCheckCode() != 0) {
- Logger.warn("Metadata certificate-verification FAILED!"
- + " Metadata: " + entityDes.getEntityID()
- + " StatusCode:" + result.getCertificateCheckCode());
- throw new FilterException("Metadata certificate-verification FAILED!"
- + " Metadata: " + entityDes.getEntityID()
- + " StatusCode:" + result.getCertificateCheckCode());
-
- }
-
- Logger.debug("SAML metadata for entityID:" + entityDes.getEntityID() + " is valid");
+ } else if (metadata instanceof EntitiesDescriptor) {
+ EntitiesDescriptor entitiesDesc = (EntitiesDescriptor) metadata;
+ if (entitiesDesc.getEntityDescriptors() != null &&
+ entitiesDesc.getEntityDescriptors().size() > 1) {
+ String nameForLogging = entitiesDesc.getName();
+ if (MiscUtil.isEmpty(nameForLogging))
+ nameForLogging = entitiesDesc.getID();
+
+ checkSignature(metadata, nameForLogging);
+
+ } else {
+ Logger.warn("Metadata root-element is of type 'EntitiesDescriptor' but only include one 'EntityDescriptor'");
+ throw new FilterException("Metadata root-element is not of type 'EntitiesDescriptor' but only include one 'EntityDescriptor");
+
+ }
+
+ } else {
+ Logger.warn("Metadata root-element is not of type 'EntityDescriptor' or 'EntitiesDescriptor'");
+ throw new FilterException("Metadata root-element is not of type 'EntityDescriptor' or 'EntitiesDescriptor'");
+
+ }
+
+ }
+
+ private void checkSignature(XMLObject metadata, String nameForLogging) throws FilterException {
+ if (((EntityDescriptor) metadata).isSigned()) {
+ //check signature;
+ try {
+ byte[] serialized = DOMUtils.serializeNode(metadata.getDOM(), "UTF-8");
+
+ SignatureVerificationUtils sigVerify =
+ new SignatureVerificationUtils();
+ IVerifiyXMLSignatureResponse result = sigVerify.verify(
+ serialized, trustProfileID);
- } catch (MOAIDException | TransformerFactoryConfigurationError | TransformerException | IOException e) {
- Logger.error("Metadata verification for Entity:" + entityDes.getEntityID()
- + " has an interal error.", e);
- throw new FilterException("Metadata verification has an interal error."
- + " Message:" + e.getMessage());
+ //check signature-verification result
+ if (result.getSignatureCheckCode() != 0) {
+ Logger.warn("Metadata signature-verification FAILED!"
+ + " Metadata: " + nameForLogging
+ + " StatusCode:" + result.getSignatureCheckCode());
}
+ if (result.getCertificateCheckCode() != 0) {
+ Logger.warn("Metadata certificate-verification FAILED!"
+ + " Metadata: " + nameForLogging
+ + " StatusCode:" + result.getCertificateCheckCode());
+ throw new FilterException("Metadata certificate-verification FAILED!"
+ + " Metadata: " + nameForLogging
+ + " StatusCode:" + result.getCertificateCheckCode());
+
+ }
- } else {
- Logger.warn("Metadata root-element MUST be signed.");
- throw new FilterException("Metadata root-element MUST be signed.'");
+ Logger.debug("SAML metadata for entityID:" + nameForLogging + " is valid");
+
+ } catch (MOAIDException | TransformerFactoryConfigurationError | TransformerException | IOException e) {
+ Logger.error("Metadata verification for Entity:" + nameForLogging
+ + " has an interal error.", e);
+ throw new FilterException("Metadata verification has an interal error."
+ + " Message:" + e.getMessage());
}
-
+
+
} else {
- Logger.warn("Metadata root-element is not of type 'EntityDescriptor'");
- throw new FilterException("Metadata root-element is not of type 'EntityDescriptor'");
+ Logger.warn("Metadata root-element MUST be signed.");
+ throw new FilterException("Metadata root-element MUST be signed.'");
}
diff --git a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties
index b88df0b9d..1a2f0d1d3 100644
--- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties
+++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties
@@ -271,6 +271,8 @@ eIDAS.11=Received eIDAS Error-Response. Reason:{0}
eIDAS.12=Received eIDAS AuthnRequest is not valid. Reason:{0}
eIDAS.13=Generation of eIDAS Response FAILED. Reason:{0}
eIDAS.14=eIDAS Response validation FAILED: LevelOfAssurance {0} is to low.
+eIDAS.15=Generation of eIDAS Response FAILED. Required attribute: {0} is NOT available.
+eIDAS.16=eIDAS Response attribute-validation FAILED. Attribute:{0} Reason: {1}.
pvp2.01=Fehler beim kodieren der PVP2 Antwort
pvp2.02=Ungueltiges Datumsformat
diff --git a/id/server/idserverlib/src/main/resources/resources/properties/protocol_response_statuscodes_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/protocol_response_statuscodes_de.properties
index e72a28046..c6d0844ce 100644
--- a/id/server/idserverlib/src/main/resources/resources/properties/protocol_response_statuscodes_de.properties
+++ b/id/server/idserverlib/src/main/resources/resources/properties/protocol_response_statuscodes_de.properties
@@ -228,6 +228,8 @@ eIDAS.11=1302
eIDAS.12=1305
eIDAS.13=1307
eIDAS.14=1301
+eIDAS.15=1307
+eIDAS.16=1301
pvp2.01=6100
pvp2.06=6100
diff --git a/id/server/idserverlib/src/main/resources/resources/templates/pvp_postbinding_template.html b/id/server/idserverlib/src/main/resources/resources/templates/pvp_postbinding_template.html
index 2f93428b5..64e88a688 100644
--- a/id/server/idserverlib/src/main/resources/resources/templates/pvp_postbinding_template.html
+++ b/id/server/idserverlib/src/main/resources/resources/templates/pvp_postbinding_template.html
@@ -1,9 +1,9 @@
## ## Velocity Template for SAML 2 HTTP-POST binding ## ## Velocity
-context may contain the following properties ## action - String - the
-action URL for the form ## RelayState - String - the relay state for the
-message ## SAMLRequest - String - the Base64 encoded SAML Request ##
-SAMLResponse - String - the Base64 encoded SAML Response
-
+##context may contain the following properties ## action - String - the
+##action URL for the form ## RelayState - String - the relay state for the
+##message ## SAMLRequest - String - the Base64 encoded SAML Request ##
+##SAMLResponse - String - the Base64 encoded SAML Response
+<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<body onload="document.forms[0].submit()">
diff --git a/id/server/idserverlib/src/main/resources/resources/templates/saml2-post-binding-moa.vm b/id/server/idserverlib/src/main/resources/resources/templates/saml2-post-binding-moa.vm
deleted file mode 100644
index 8beb601c6..000000000
--- a/id/server/idserverlib/src/main/resources/resources/templates/saml2-post-binding-moa.vm
+++ /dev/null
@@ -1,38 +0,0 @@
-##
-## Velocity Template for SAML 2 HTTP-POST binding
-##
-## Velocity context may contain the following properties
-## action - String - the action URL for the form
-## RelayState - String - the relay state for the message
-## SAMLRequest - String - the Base64 encoded SAML Request
-## SAMLResponse - String - the Base64 encoded SAML Response
-## Contains target attribute to delegate PEPS authentication out of iFrame
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-
- <body onload="document.forms[0].submit()">
- <noscript>
- <p>
- <strong>Note:</strong> Since your browser does not support JavaScript,
- you must press the Continue button once to proceed.
- </p>
- </noscript>
-
- <form action="${action}" method="post" target="_top">
- <div>
- #if($RelayState)<input type="hidden" name="RelayState" value="${RelayState}"/>#end
-
- #if($SAMLRequest)<input type="hidden" name="SAMLRequest" value="${SAMLRequest}"/>#end
-
- #if($SAMLResponse)<input type="hidden" name="SAMLResponse" value="${SAMLResponse}"/>#end
-
- </div>
- <noscript>
- <div>
- <input type="submit" value="Continue"/>
- </div>
- </noscript>
- </form>
-
- </body>
-</html> \ No newline at end of file
diff --git a/id/server/idserverlib/src/main/resources/resources/templates/stork2_consent.html b/id/server/idserverlib/src/main/resources/resources/templates/stork2_consent.html
deleted file mode 100644
index 0ab41f146..000000000
--- a/id/server/idserverlib/src/main/resources/resources/templates/stork2_consent.html
+++ /dev/null
@@ -1,438 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
-
- <!-- MOA-ID 2.x BKUSelection Layout CSS -->
- <style type="text/css">
- @media screen and (min-width: 650px) {
-
- body {
- margin:0;
- padding:0;
- color : #000;
- background-color : #fff;
- text-align: center;
- background-color: #6B7B8B;
- }
-
- #bku_header h2 {
- font-size: 0.8em;
- }
-
-
- #page {
- display: block;
- border: 2px solid rgb(0,0,0);
- width: 650px;
- height: 460px;
- margin: 0 auto;
- margin-top: 5%;
- position: relative;
- border-radius: 25px;
- background: rgb(255,255,255);
- }
-
- #page1 {
- text-align: center;
- }
-
- #main {
- /* clear:both; */
- position:relative;
- margin: 0 auto;
- width: 250px;
- text-align: center;
- }
-
- .OA_header {
- /* background-color: white;*/
- font-size: 20pt;
- margin-bottom: 25px;
- margin-top: 25px;
- }
-
- #leftcontent {
- /*float:left; */
- width:250px;
- margin-bottom: 25px;
- text-align: left;
- border: 1px solid rgb(0,0,0);
- }
-
- #selectArea {
- font-size: 15px;
- padding-bottom: 65px;
- }
-
- #leftcontent {
- width: 300px;
- margin-top: 30px;
- }
-
- #bku_header {
- height: 5%;
- padding-bottom: 3px;
- padding-top: 3px;
- }
-
- #bkulogin {
- overflow:auto;
- min-width: 190px;
- height: 260px;
- padding: 20px;
- }
-
- h2#tabheader{
- font-size: 1.1em;
- padding-left: 2%;
- padding-right: 2%;
- position: relative;
- }
-
- .setAssertionButton_full {
- background: #efefef;
- cursor: pointer;
- margin-top: 15px;
- width: 100px;
- height: 30px
- }
-
- #leftbutton {
- width: 30%;
- float:left;
- margin-left: 40px;
- }
-
- #rightbutton {
- width: 30%;
- float:right;
- margin-right: 45px;
- text-align: right;
- }
-
- button {
- height: 25px;
- width: 75px;
- margin-bottom: 10px;
- }
-
- #validation {
- position: absolute;
- bottom: 0px;
- margin-left: 270px;
- padding-bottom: 10px;
- }
-
- }
-
- @media screen and (max-width: 205px) {
- #bku_header h2 {
- font-size: 0.8em;
- margin-top: -0.4em;
- padding-top: 0.4em;
- }
-
- #bkulogin {
- min-height: 150px;
- padding: 20px;
- }
- }
-
- @media screen and (max-width: 249px) and (min-width: 206px) {
- #bku_header h2 {
- font-size: 0.9em;
- margin-top: -0.45em;
- padding-top: 0.45em;
- }
-
- #bkulogin {
- height: 180px;
- padding: 20px;
- }
- }
-
- @media screen and (max-width: 299px) and (min-width: 250px) {
- #bku_header h2 {
- font-size: 1.1em;
- margin-top: -0.55em;
- padding-top: 0.55em;
- }
- }
-
- @media screen and (max-width: 649px) and (min-width: 400px) {
- #bku_header h2 {
- font-size: 1.3em;
- margin-top: -0.65em;
- padding-top: 0.65em;
- }
- }
-
-
-
- @media screen and (max-width: 649px) {
-
- body {
- margin:0;
- padding:0;
- color : #000;
- text-align: center;
- font-size: 100%;
- background-color: ${MAIN_BACKGOUNDCOLOR};
- }
-
- #page {
- visibility: hidden;
- margin-top: 0%;
- }
-
- #page1 {
- visibility: hidden;
- }
-
- #main {
- visibility: hidden;
- }
-
- #validation {
- visibility: hidden;
- display: none;
- }
-
- .OA_header {
- margin-bottom: 0px;
- margin-top: 0px;
- font-size: 0pt;
- visibility: hidden;
- }
-
- #leftcontent {
- visibility: visible;
- margin-bottom: 0px;
- text-align: left;
- border:none;
- vertical-align: middle;
- min-height: 173px;
- min-width: 204px;
-
- }
-
- #bku_header {
- height: 10%;
- min-height: 1.2em;
- margin-top: 1%;
- }
-
- h2#tabheader{
- padding-left: 2%;
- padding-right: 2%;
- position: relative;
- top: 50%;
- }
-
- #bkulogin {
- min-width: 190px;
- height: 155px;
- padding: 20px;
- }
-
- .setAssertionButton_full {
- background: #efefef;
- cursor: pointer;
- margin-top: 15px;
- width: 70px;
- height: 25px;
- }
-
- input[type=button] {
-/* height: 11%; */
- width: 70%;
- }
- }
-
- * {
- margin: 0;
- padding: 0;
- font-family: ${FONTTYPE};
- }
-
- #selectArea {
- padding-top: 10px;
- padding-bottom: 55px;
- padding-left: 10px;
- }
-
- .setAssertionButton {
- background: #efefef;
- cursor: pointer;
- margin-top: 15px;
- width: 70px;
- height: 25px;
- }
-
- #leftbutton {
- width: 35%;
- float:left;
- margin-left: 15px;
- }
-
- #rightbutton {
- width: 35%;
- float:right;
- margin-right: 25px;
- text-align: right;
- }
-
- .verticalcenter {
- vertical-align: middle;
- }
-
- input {
- /*border:1px solid #000;*/
- cursor: pointer;
- }
-
-
- #installJava, #BrowserNOK {
- clear:both;
- font-size:0.8em;
- padding:4px;
- }
-
- .selectText{
-
- }
-
- .selectTextHeader{
-
- }
-
- .sendButton {
- width: 30%;
- margin-bottom: 1%;
- }
-
- #leftcontent a {
- text-decoration:none;
- color: #000;
- /* display:block;*/
- padding:4px;
- }
-
- #leftcontent a:hover, #leftcontent a:focus, #leftcontent a:active {
- text-decoration:underline;
- color: #000;
- }
-
- .infobutton {
- background-color: #005a00;
- color: white;
- font-family: serif;
- text-decoration: none;
- padding-top: 2px;
- padding-right: 4px;
- padding-bottom: 2px;
- padding-left: 4px;
- font-weight: bold;
- }
-
- .hell {
- background-color : ${MAIN_BACKGOUNDCOLOR};
- color: ${MAIN_COLOR};
- }
-
- .dunkel {
- background-color: ${HEADER_BACKGROUNDCOLOR};
- color: ${HEADER_COLOR};
- }
-
- .main_header {
- color: black;
- font-size: 32pt;
- position: absolute;
- right: 10%;
- top: 40px;
-
- }
-
- #controls {
- text-align: right;
- }
-
- </style>
-<!-- MOA-ID 2.x BKUSelection JavaScript fucnctions-->
-<script type="text/javascript">
- function isIE() {
- return (/MSIE (\d+\.\d+);/.test(navigator.userAgent));
- }
- function isFullscreen() {
- try {
- return ((top.innerWidth == screen.width) && (top.innerHeight == screen.height));
- } catch (e) {
- return false;
- }
- }
- function isActivexEnabled() {
- var supported = null;
- try {
- supported = !!new ActiveXObject("htmlfile");
- } catch (e) {
- supported = false;
- }
- return supported;
- }
- function generateIFrame(iFrameURL) {
- var el = document.getElementById("bkulogin");
- var width = el.clientWidth;
- var heigth = el.clientHeight - 20;
- var parent = el.parentNode;
-
- iFrameURL += "&heigth=" + heigth;
- iFrameURL += "&width=" + width;
-
- var iframe = document.createElement("iframe");
- iframe.setAttribute("src", iFrameURL);
- iframe.setAttribute("width", el.clientWidth - 1);
- iframe.setAttribute("height", el.clientHeight - 1);
- iframe.setAttribute("frameborder", "0");
- iframe.setAttribute("scrolling", "no");
- iframe.setAttribute("title", "Login");
- parent.replaceChild(iframe, el);
- }
- function onChangeChecks() {
- if (top.innerWidth < 650) {
- document.getElementById("moaidform").setAttribute("target","_parent");
- } else {
- document.getElementById("moaidform").removeAttribute("target");
- }
-
- }
- </script>
-<title>Informationsfreigabe</title>
-</head>
-<body onload="onChangeChecks();" onresize="onChangeChecks();">
- <div id="page">
- <div id="page1" class="case selected-case" role="main">
- <h2 class="OA_header" role="heading">STORK Informationsfreigabe</h2>
- <div id="main">
- <div id="leftcontent" class="hell" role="application">
- <form method="POST" action="${action}">
- <div id="bku_header" class="dunkel">
- <h2 id="tabheader" class="dunkel" role="heading">STORK Informationsfreigabe</h2>
- </div>
- <div id="bkulogin" class="hell" role="form">
- W&auml;hlen Sie jene Daten, die, wenn verf&uuml;gbar, an ein Drittland weitergegeben werden sollen:</br>
- <table>
- ${tablecontent}
- </table>
- </div>
- <div id="controls" class="hell">
- <input type="submit" value="weiter" />
- </div>
- </form>
- </div>
- </div>
- </div>
- </div>
-</body>
-</html> \ No newline at end of file
diff --git a/id/server/idserverlib/src/main/resources/resources/templates/stork2_postbinding_template.html b/id/server/idserverlib/src/main/resources/resources/templates/stork2_postbinding_template.html
deleted file mode 100644
index f901351a2..000000000
--- a/id/server/idserverlib/src/main/resources/resources/templates/stork2_postbinding_template.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-
-<body onload="document.forms[0].submit()">
- <noscript>
- <p>
- <strong>Note:</strong> Since your browser does not support
- JavaScript, you must press the Continue button once to proceed.
- </p>
- </noscript>
-
-
- <div id="alert">Your login is being processed. Thank you for
- waiting.</div>
-
- <style type="text/css">
-<!--
-#alert {
- margin: 100px 250px;
- font-family: Verdana, Arial, Helvetica, sans-serif;
- font-size: 14px;
- font-weight: normal;
-}
--->
-</style>
-
- <form action="${action}" method="post" target="_self">
- <div>
- #if($RelayState)<input type="hidden" name="RelayState"
- value="${RelayState}" />#end #if($SAMLRequest)<input type="hidden"
- name="SAMLRequest" value="${SAMLRequest}" />#end #if($SAMLResponse)<input
- type="hidden" name="SAMLResponse" value="${SAMLResponse}" />#end
-
- </div>
- <noscript>
- <div>
- <input type="submit" value="Continue" />
- </div>
- </noscript>
- </form>
-
-</body>
-</html>
diff --git a/id/server/moa-id-commons/pom.xml b/id/server/moa-id-commons/pom.xml
index 51cb6d5af..c4007fc80 100644
--- a/id/server/moa-id-commons/pom.xml
+++ b/id/server/moa-id-commons/pom.xml
@@ -323,9 +323,10 @@
<target>1.7</target>
</configuration>
</plugin>
- <plugin>
+ <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
+ <version>3.0.2</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
@@ -375,7 +376,7 @@
</executions>
</plugin>
- <plugin>
+<!-- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
@@ -390,7 +391,7 @@
</goals>
</execution>
</executions>
- </plugin>
+ </plugin> -->
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.1.1</version>
diff --git a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/MOAIDConstants.java b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/MOAIDConstants.java
index 6d573efe8..e9f9a7e80 100644
--- a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/MOAIDConstants.java
+++ b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/MOAIDConstants.java
@@ -36,6 +36,8 @@ public class MOAIDConstants {
//general configuration constants
+ public static final String DEFAULT_CONTENT_TYPE_HTML_UTF8 = "text/html; charset=UTF-8";
+
public static final String FILE_URI_PREFIX = "file:/";
public static final String PREFIX_WPBK = "urn:publicid:gv.at:wbpk+";
diff --git a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/data/CPEPS.java b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/data/CPEPS.java
index a88aa2171..525a660b4 100644
--- a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/data/CPEPS.java
+++ b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/data/CPEPS.java
@@ -62,11 +62,23 @@ public class CPEPS {
this.isXMLSignatureSupported = isXMLSignatureSupported;
}
+
+ public String getFullCountryCode() {
+ return countryCode;
+ }
+
/**
* Gets the country code of this C-PEPS
* @return ISO country code
*/
public String getCountryCode() {
+ if (countryCode != null &&
+ countryCode.contains("-")) {
+ //remove trailing information to country code
+ return countryCode.substring(0, countryCode.indexOf("-"));
+
+ }
+
return countryCode;
}
diff --git a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/config/ConfigurationMigrationUtils.java b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/config/ConfigurationMigrationUtils.java
index 61b08f3a6..b8284c8f9 100644
--- a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/config/ConfigurationMigrationUtils.java
+++ b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/config/ConfigurationMigrationUtils.java
@@ -981,13 +981,17 @@ public class ConfigurationMigrationUtils {
}
// transfer the incoming data to the database model
stork.setStorkLogonEnabled(Boolean.parseBoolean(oa.get(MOAIDConfigurationConstants.SERVICE_AUTH_STORK_ENABLED)));
- if (MiscUtil.isNotEmpty(oa.get(MOAIDConfigurationConstants.SERVICE_AUTH_STORK_MINQAALEVEL)))
+ if (MiscUtil.isNotEmpty(oa.get(MOAIDConfigurationConstants.SERVICE_AUTH_STORK_MINQAALEVEL))) {
try {
+ stork.seteIDAS_LOA(oa.get(MOAIDConfigurationConstants.SERVICE_AUTH_STORK_MINQAALEVEL));
stork.setQaa(Integer.valueOf(oa.get(MOAIDConfigurationConstants.SERVICE_AUTH_STORK_MINQAALEVEL)));
+
} catch (NumberFormatException e) {
Logger.info("Downgraded OA config found -> change eIDAS LoA to STORK QAA");
stork.setQaa(4);
+
}
+ }
if (MiscUtil.isNotEmpty(oa.get(MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES))
&& oa.get(MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES).equals(MOAIDConfigurationConstants.PREFIX_VIDP))
diff --git a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/util/Constants.java b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/util/Constants.java
index 260b2ecb1..129478270 100644
--- a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/util/Constants.java
+++ b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/util/Constants.java
@@ -449,7 +449,7 @@ public interface Constants {
//TODO: update to eIDAS prefix
/** URN prefix for context dependent id (eIDAS). */
- public static final String URN_PREFIX_EIDAS = URN_PREFIX + ":storkid";
+ public static final String URN_PREFIX_EIDAS = URN_PREFIX + ":eidasid";
/** URN prefix for context dependent id. */
public static final String URN_PREFIX_BASEID = URN_PREFIX + ":baseid";
diff --git a/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/builder/GUIFormBuilderImpl.java b/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/builder/GUIFormBuilderImpl.java
index e77933986..e8cd60afb 100644
--- a/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/builder/GUIFormBuilderImpl.java
+++ b/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/builder/GUIFormBuilderImpl.java
@@ -43,6 +43,7 @@ import org.springframework.stereotype.Service;
import at.gv.egovernment.moa.id.auth.frontend.exception.GUIBuildException;
import at.gv.egovernment.moa.id.auth.frontend.velocity.VelocityProvider;
+import at.gv.egovernment.moa.id.commons.MOAIDConstants;
import at.gv.egovernment.moa.id.commons.api.AuthConfiguration;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;
@@ -54,7 +55,7 @@ import at.gv.egovernment.moa.util.MiscUtil;
@Service("guiFormBuilder")
public class GUIFormBuilderImpl implements IGUIFormBuilder {
- private static final String DEFAULT_CONTENT_TYPE = "text/html; charset=UTF-8";
+ private static final String DEFAULT_CONTENT_TYPE = MOAIDConstants.DEFAULT_CONTENT_TYPE_HTML_UTF8;
private static final String CONFIG_HTMLTEMPLATES_DIR = "htmlTemplates/";
private static final String CLASSPATH_HTMLTEMPLATES_DIR = "templates/";
diff --git a/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/builder/ServiceProviderSpecificGUIFormBuilderConfiguration.java b/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/builder/ServiceProviderSpecificGUIFormBuilderConfiguration.java
index 0a5cdaf3e..63df81b3c 100644
--- a/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/builder/ServiceProviderSpecificGUIFormBuilderConfiguration.java
+++ b/id/server/moa-id-frontend-resources/src/main/java/at/gv/egovernment/moa/id/auth/frontend/builder/ServiceProviderSpecificGUIFormBuilderConfiguration.java
@@ -126,12 +126,12 @@ public class ServiceProviderSpecificGUIFormBuilderConfiguration extends Abstract
try {
for (CPEPS current : oaParam.getPepsList()) {
String countryName = null;
- if (MiscUtil.isNotEmpty(MOAIDAuthConstants.COUNTRYCODE_XX_TO_NAME.get(current.getCountryCode().toUpperCase())))
- countryName = MOAIDAuthConstants.COUNTRYCODE_XX_TO_NAME.get(current.getCountryCode().toUpperCase());
+ if (MiscUtil.isNotEmpty(MOAIDAuthConstants.COUNTRYCODE_XX_TO_NAME.get(current.getFullCountryCode().toUpperCase())))
+ countryName = MOAIDAuthConstants.COUNTRYCODE_XX_TO_NAME.get(current.getFullCountryCode().toUpperCase());
else
- countryName = current.getCountryCode().toUpperCase();
+ countryName = current.getFullCountryCode().toUpperCase();
- pepslist += "<option value=" + current.getCountryCode() + ">"
+ pepslist += "<option value=" + current.getFullCountryCode() + ">"
+ countryName
+ "</option>\n";
diff --git a/id/server/moa-id-jaxb_classes/pom.xml b/id/server/moa-id-jaxb_classes/pom.xml
index 9dbb28dfe..3d205bb06 100644
--- a/id/server/moa-id-jaxb_classes/pom.xml
+++ b/id/server/moa-id-jaxb_classes/pom.xml
@@ -52,4 +52,18 @@
</profiles>
<version>${moa-id-version}</version>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
</project> \ No newline at end of file
diff --git a/id/server/modules/moa-id-module-eIDAS/pom.xml b/id/server/modules/moa-id-module-eIDAS/pom.xml
index 174ce40cb..55d02e82a 100644
--- a/id/server/modules/moa-id-module-eIDAS/pom.xml
+++ b/id/server/modules/moa-id-module-eIDAS/pom.xml
@@ -12,11 +12,11 @@
<properties>
<repositoryPath>${basedir}/../../../../repository</repositoryPath>
- <eidas-commons.version>1.1.0</eidas-commons.version>
- <eidas-light-commons.version>1.1.0</eidas-light-commons.version>
- <eidas-saml-engine.version>1.1.0</eidas-saml-engine.version>
- <eidas-encryption.version>1.1.0</eidas-encryption.version>
- <eidas-configmodule.version>1.1.0</eidas-configmodule.version>
+ <eidas-commons.version>1.2.0</eidas-commons.version>
+ <eidas-light-commons.version>1.2.0</eidas-light-commons.version>
+ <eidas-saml-engine.version>1.2.0</eidas-saml-engine.version>
+ <eidas-encryption.version>1.2.0</eidas-encryption.version>
+ <eidas-configmodule.version>1.2.0</eidas-configmodule.version>
</properties>
@@ -166,6 +166,12 @@
<!-- <scope>provided</scope> -->
</dependency>
+ <dependency>
+ <groupId>com.ibm.icu</groupId>
+ <artifactId>icu4j</artifactId>
+ <version>58.2</version>
+ </dependency>
+
</dependencies>
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 02c9a8f5d..369d77863 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
@@ -22,6 +22,7 @@
*/
package at.gv.egovernment.moa.id.auth.modules.eidas;
+import org.apache.xml.security.signature.XMLSignature;
import org.opensaml.xml.encryption.EncryptionConstants;
import org.opensaml.xml.signature.SignatureConstants;
//import eu.eidas.auth.engine.core.validator.eidas.EIDASAttributes;
@@ -45,7 +46,8 @@ public class Constants {
public static final String eIDAS_SAML_ENGINE_NAME_ID_CLASS = "class";
//default implementations for eIDAS SAML-engine functionality
- public static final String SAML_SIGNING_IMPLENTATION = "at.gv.egovernment.moa.id.auth.modules.eidas.config.MOASWSigner";
+ //public static final String SAML_SIGNING_IMPLENTATION = "at.gv.egovernment.moa.id.auth.modules.eidas.config.MOASWSigner";
+ public static final String SAML_SIGNING_IMPLENTATION = "at.gv.egovernment.moa.id.auth.modules.eidas.config.MOAExtendedSWSigner";
public static final String SAML_ENCRYPTION_IMPLENTATION = "at.gv.egovernment.moa.id.auth.modules.eidas.config.ModifiedEncryptionSW";
//configuration property keys
@@ -96,8 +98,6 @@ public class Constants {
public static final int eIDAS_REVERSIONSLOG_METADATA = 3400;
public static final int eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST = 3401;
public static final int eIDAS_REVERSIONSLOG_IDP_AUTHRESPONSE = 3402;
- public static final int eIDAS_REVERSIONSLOG_SP_AUTHREQUEST= 3403;
- public static final int eIDAS_REVERSIONSLOG_SP_AUTHRESPONSE= 3404;
//metadata constants
// public final static Map<String, EidasAttributesTypes> METADATA_POSSIBLE_ATTRIBUTES = Collections.unmodifiableMap(
@@ -133,16 +133,20 @@ public class Constants {
public static final String METADATA_ALLOWED_ALG_DIGIST =
- SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256 + ";" +
- SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512 ;
+ SignatureConstants.ALGO_ID_DIGEST_SHA256 + ";" +
+ SignatureConstants.ALGO_ID_DIGEST_SHA512 ;
public static final String METADATA_ALLOWED_ALG_SIGN =
SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256 + ";" +
- SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512;
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512 + ";" +
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1 + ";" +
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1;
public static final String METADATA_ALLOWED_ALG_ENCRYPT =
EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM + ";" +
EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM + ";" +
- EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM;
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM + ";" +
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128 + ";" +
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256;
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java
new file mode 100644
index 000000000..e08d302f6
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java
@@ -0,0 +1,479 @@
+/*
+ * 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.config;
+
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.xml.security.signature.XMLSignature;
+import org.opensaml.Configuration;
+import org.opensaml.common.impl.SAMLObjectContentReference;
+import org.opensaml.security.SAMLSignatureProfileValidator;
+import org.opensaml.xml.io.MarshallingException;
+import org.opensaml.xml.security.SecurityConfiguration;
+import org.opensaml.xml.security.SecurityException;
+import org.opensaml.xml.security.SecurityHelper;
+import org.opensaml.xml.security.credential.Credential;
+import org.opensaml.xml.security.keyinfo.KeyInfoGenerator;
+import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory;
+import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorManager;
+import org.opensaml.xml.security.keyinfo.NamedKeyInfoGeneratorManager;
+import org.opensaml.xml.security.x509.X509Credential;
+import org.opensaml.xml.signature.KeyInfo;
+import org.opensaml.xml.signature.SignableXMLObject;
+import org.opensaml.xml.signature.Signature;
+import org.opensaml.xml.signature.SignatureException;
+import org.opensaml.xml.signature.SignatureValidator;
+import org.opensaml.xml.signature.Signer;
+import org.opensaml.xml.validation.ValidationException;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.sun.istack.Nullable;
+
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAWhiteListConfigurator;
+import at.gv.egovernment.moa.logging.Logger;
+import eu.eidas.auth.commons.EidasErrorKey;
+import eu.eidas.auth.engine.configuration.SamlEngineConfigurationException;
+import eu.eidas.auth.engine.configuration.dom.ConfigurationAdapter;
+import eu.eidas.auth.engine.configuration.dom.ConfigurationKey;
+import eu.eidas.auth.engine.configuration.dom.KeyStoreSignatureConfigurator;
+import eu.eidas.auth.engine.configuration.dom.SignatureConfiguration;
+import eu.eidas.auth.engine.core.ProtocolSignerI;
+import eu.eidas.auth.engine.core.impl.BouncyCastleBootstrap;
+import eu.eidas.auth.engine.core.impl.CertificateValidator;
+import eu.eidas.auth.engine.metadata.MetadataSignerI;
+import eu.eidas.auth.engine.xml.opensaml.CertificateUtil;
+import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
+import eu.eidas.samlengineconfig.CertificateConfigurationManager;
+import eu.eidas.util.Preconditions;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAExtendedSWSigner implements ProtocolSignerI, MetadataSignerI {
+
+ private static final String DEFAULT_SIGNATURE_ALGORITHM = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";
+ private static final ImmutableSet<String> ALLOWED_ALGORITHMS_FOR_SIGNING;
+ private static final ImmutableSet<String> ALLOWED_ALGORITHMS_FOR_VERIFYING;
+ private static final ImmutableSet<String> DEFAULT_ALGORITHM_WHITE_LIST;
+ private static final String DEFAULT_DIGEST_ALGORITHM = "http://www.w3.org/2001/04/xmlenc#sha512";
+ private static final ImmutableMap<Object, Object> SIGNATURE_TO_DIGEST_ALGORITHM_MAP;
+ private final boolean checkedValidityPeriod;
+ private final boolean disallowedSelfSignedCertificate;
+ private final boolean responseSignAssertions;
+ private final ImmutableSet<String> signatureAlgorithmWhiteList;
+ private final X509Credential privateSigningCredential;
+ private final X509Credential publicSigningCredential;
+ private final X509Credential privateMetadataSigningCredential;
+ private final X509Credential publicMetadataSigningCredential;
+ private final ImmutableList<X509Credential> trustedCredentials;
+ private final String signatureAlgorithm;
+
+ public MOAExtendedSWSigner(Map<String, String> properties) throws SamlEngineConfigurationException {
+ this(new KeyStoreSignatureConfigurator().getSignatureConfiguration(properties));
+
+ }
+
+ /**
+ * @param configManager
+ * @throws SamlEngineConfigurationException
+ */
+ public MOAExtendedSWSigner(CertificateConfigurationManager configManager) throws SamlEngineConfigurationException {
+ this(new KeyStoreSignatureConfigurator().getSignatureConfiguration(
+ ConfigurationAdapter.adapt(configManager).getInstances().get(Constants.eIDAS_SAML_ENGINE_NAME).getConfigurationEntries().get(ConfigurationKey.SIGNATURE_CONFIGURATION.getKey()).getParameters()));
+
+ }
+
+ protected MOAExtendedSWSigner(SignatureConfiguration signatureConfiguration)
+ throws SamlEngineConfigurationException {
+ this(signatureConfiguration.isCheckedValidityPeriod(),
+ signatureConfiguration.isDisallowedSelfSignedCertificate(),
+ signatureConfiguration.isResponseSignAssertions(),
+ signatureConfiguration.getSignatureKeyAndCertificate(), signatureConfiguration.getTrustedCertificates(),
+ signatureConfiguration.getSignatureAlgorithm(), signatureConfiguration.getSignatureAlgorithmWhiteList(),
+ signatureConfiguration.getMetadataSigningKeyAndCertificate());
+ }
+
+ protected MOAExtendedSWSigner(boolean checkedValidityPeriod, boolean disallowedSelfSignedCertificate,
+ boolean responseSignAssertions, KeyStore.PrivateKeyEntry signatureKeyAndCertificate,
+ ImmutableSet<X509Certificate> trustedCertificates, String signatureAlgorithmVal,
+ String signatureAlgorithmWhiteListStr,
+ KeyStore.PrivateKeyEntry metadataSigningKeyAndCertificate)
+ throws SamlEngineConfigurationException {
+ Preconditions.checkNotNull(signatureKeyAndCertificate, "signatureKeyAndCertificate");
+ Preconditions.checkNotNull(trustedCertificates, "trustedCertificates");
+ String signatureAlg = signatureAlgorithmVal;
+
+ if (StringUtils.isBlank(signatureAlg))
+ signatureAlg = DEFAULT_SIGNATURE_ALGORITHM;
+
+ else {
+ signatureAlg = validateSigningAlgorithm(signatureAlg);
+
+ }
+
+ ImmutableSet signatureAlgorithmWhiteSet = MOAWhiteListConfigurator.getAllowedAlgorithms(
+ DEFAULT_ALGORITHM_WHITE_LIST, ALLOWED_ALGORITHMS_FOR_VERIFYING, signatureAlgorithmWhiteListStr);
+
+ this.checkedValidityPeriod = checkedValidityPeriod;
+ this.disallowedSelfSignedCertificate = disallowedSelfSignedCertificate;
+ this.responseSignAssertions = responseSignAssertions;
+ this.trustedCredentials = CertificateUtil.getListOfCredential(trustedCertificates);
+ this.signatureAlgorithmWhiteList = signatureAlgorithmWhiteSet;
+ this.signatureAlgorithm = signatureAlg;
+ this.privateSigningCredential = CertificateUtil.createCredential(signatureKeyAndCertificate);
+ this.publicSigningCredential = CertificateUtil
+ .toCredential((X509Certificate) signatureKeyAndCertificate.getCertificate());
+
+ if (null != metadataSigningKeyAndCertificate) {
+ this.privateMetadataSigningCredential = CertificateUtil.createCredential(metadataSigningKeyAndCertificate);
+ this.publicMetadataSigningCredential = CertificateUtil
+ .toCredential((X509Certificate) metadataSigningKeyAndCertificate.getCertificate());
+ } else {
+ this.privateMetadataSigningCredential = null;
+ this.publicMetadataSigningCredential = null;
+ }
+ }
+
+ private static X509Certificate getSignatureCertificate(Signature signature) throws EIDASSAMLEngineException {
+ KeyInfo keyInfo = signature.getKeyInfo();
+ return CertificateUtil.toCertificate(keyInfo);
+ }
+
+ public static String validateDigestAlgorithm(String signatureAlgorithmName)
+ throws SamlEngineConfigurationException {
+
+ if (StringUtils.isBlank(signatureAlgorithmName)) {
+ return DEFAULT_DIGEST_ALGORITHM;
+
+ }
+
+ //BUGFIX: toLowerCase from original eIDAS SAML-engine produce problems with MGF1 signature algorithms
+ String canonicalAlgorithm = signatureAlgorithmName.trim();
+ String digestAlgorithm = (String) SIGNATURE_TO_DIGEST_ALGORITHM_MAP.get(canonicalAlgorithm);
+ if (null != digestAlgorithm) {
+ return digestAlgorithm;
+
+ }
+ String msg = "Signing algorithm \"" + signatureAlgorithmName
+ + "\" does not contain an allowed digest algorithm";
+
+ Logger.error(msg);
+ throw new SamlEngineConfigurationException(msg);
+
+ }
+
+ public static String validateSigningAlgorithm(@Nullable String signatureAlgorithmName)
+ throws SamlEngineConfigurationException {
+ if ((signatureAlgorithmName == null) || (StringUtils.isBlank(signatureAlgorithmName))) {
+ return DEFAULT_SIGNATURE_ALGORITHM;
+
+ }
+
+ //BUGFIX:: toLowerCase from original eIDAS SAML-engine produce problems with MGF1 signature algorithms
+ String canonicalAlgorithm = signatureAlgorithmName.trim();
+ if (ALLOWED_ALGORITHMS_FOR_SIGNING.contains(canonicalAlgorithm)) {
+ return canonicalAlgorithm;
+
+ }
+ String msg = "Signing algorithm \"" + signatureAlgorithmName + "\" is not allowed";
+ Logger.error(msg);
+ throw new SamlEngineConfigurationException(msg);
+
+ }
+
+ protected void checkCertificateIssuer(X509Certificate certificate) throws EIDASSAMLEngineException {
+ CertificateValidator.checkCertificateIssuer(this.disallowedSelfSignedCertificate, certificate);
+
+ }
+
+ protected void checkCertificateValidityPeriod(X509Certificate certificate) throws EIDASSAMLEngineException {
+ CertificateValidator.checkCertificateValidityPeriod(this.checkedValidityPeriod, certificate);
+
+ }
+
+ protected Signature createSignature(X509Credential credential) throws EIDASSAMLEngineException {
+ checkCertificateValidityPeriod(credential.getEntityCertificate());
+ checkCertificateIssuer(credential.getEntityCertificate());
+ Signature signature;
+ try {
+ Logger.debug("Creating an OpenSAML signature object");
+
+ signature = (Signature) Configuration.getBuilderFactory().getBuilder(Signature.DEFAULT_ELEMENT_NAME)
+ .buildObject(Signature.DEFAULT_ELEMENT_NAME);
+
+ signature.setSigningCredential(credential);
+
+ signature.setSignatureAlgorithm(getSignatureAlgorithm());
+
+ SecurityConfiguration secConfiguration = Configuration.getGlobalSecurityConfiguration();
+ NamedKeyInfoGeneratorManager keyInfoManager = secConfiguration.getKeyInfoGeneratorManager();
+ KeyInfoGeneratorManager keyInfoGenManager = keyInfoManager.getDefaultManager();
+ KeyInfoGeneratorFactory keyInfoGenFac = keyInfoGenManager.getFactory(credential);
+ KeyInfoGenerator keyInfoGenerator = keyInfoGenFac.newInstance();
+
+ KeyInfo keyInfo = keyInfoGenerator.generate(credential);
+
+ signature.setKeyInfo(keyInfo);
+ signature.setCanonicalizationAlgorithm("http://www.w3.org/2001/10/xml-exc-c14n#");
+ } catch (SecurityException e) {
+ Logger.error("ERROR : Security exception: " + e, e);
+ throw new EIDASSAMLEngineException(e);
+
+ }
+ return signature;
+ }
+
+ public X509Credential getPublicMetadataSigningCredential() {
+ return this.publicMetadataSigningCredential;
+
+ }
+
+ public X509Credential getPublicSigningCredential() {
+ return this.publicSigningCredential;
+
+ }
+
+ protected String getSignatureAlgorithm() {
+ return this.signatureAlgorithm;
+
+ }
+
+ protected ImmutableSet<String> getSignatureAlgorithmWhiteList() {
+ return this.signatureAlgorithmWhiteList;
+
+ }
+
+ private X509Credential getTrustedCertificate(Signature signature,
+ List<? extends Credential> trustedCredentialList) throws EIDASSAMLEngineException {
+ X509Certificate cert = getSignatureCertificate(signature);
+
+ X509Credential entityX509Cred = CertificateUtil.toCredential(cert);
+
+ CertificateUtil.checkTrust(entityX509Cred, trustedCredentialList);
+ checkCertificateValidityPeriod(cert);
+ checkCertificateIssuer(cert);
+ return entityX509Cred;
+
+ }
+
+ protected ImmutableList<X509Credential> getTrustedCredentials() {
+ return this.trustedCredentials;
+
+ }
+
+ private boolean isAlgorithmAllowedForVerifying(String signatureAlgorithm) {
+ return ((StringUtils.isNotBlank(signatureAlgorithm))
+ && (getSignatureAlgorithmWhiteList().contains(signatureAlgorithm.trim())));
+
+ }
+
+ public <T extends SignableXMLObject> T sign(T signableObject) throws EIDASSAMLEngineException {
+ return sign(signableObject, this.privateSigningCredential);
+
+ }
+
+ protected <T extends SignableXMLObject> T sign(T signableObject, X509Credential signingCredential)
+ throws EIDASSAMLEngineException {
+ Logger.trace("Start Sign process.");
+ try {
+ Signature signature = createSignature(signingCredential);
+ signableObject.setSignature(signature);
+
+ String digestAlgorithm = validateDigestAlgorithm(getSignatureAlgorithm());
+ List contentReferences = signature.getContentReferences();
+ if (CollectionUtils.isNotEmpty(contentReferences))
+ ((SAMLObjectContentReference) contentReferences.get(0)).setDigestAlgorithm(digestAlgorithm);
+
+ else {
+ Logger.error("Unable to set DigestMethodAlgorithm - algorithm " + digestAlgorithm + " not set");
+
+ }
+
+ Logger.trace("Marshall samlToken.");
+ Configuration.getMarshallerFactory().getMarshaller(signableObject).marshall(signableObject);
+
+ Logger.trace("Sign samlToken.");
+ Signer.signObject(signature);
+
+ } catch (MarshallingException e) {
+ Logger.error("ERROR : MarshallingException: " + e, e);
+ throw new EIDASSAMLEngineException(e);
+
+ } catch (SignatureException e) {
+ Logger.error("ERROR : Signature exception: " + e, e);
+ throw new EIDASSAMLEngineException(e);
+
+ }
+
+ return signableObject;
+ }
+
+ public <T extends SignableXMLObject> T signMetadata(T signableObject) throws EIDASSAMLEngineException {
+ if (null == this.privateMetadataSigningCredential) {
+ throw new SamlEngineConfigurationException("No metadataSigningCredential configured");
+
+ }
+ return sign(signableObject, this.privateMetadataSigningCredential);
+ }
+
+ public <T extends SignableXMLObject> T validateMetadataSignature(T signedMetadata)
+ throws EIDASSAMLEngineException {
+ return validateSignature(signedMetadata, null);
+
+ }
+
+ private SAMLSignatureProfileValidator validateSamlSignatureStructure(SignableXMLObject signableObject)
+ throws EIDASSAMLEngineException {
+ SAMLSignatureProfileValidator sigProfValidator = new SAMLSignatureProfileValidator();
+ try {
+ sigProfValidator.validate(signableObject.getSignature());
+
+ } catch (ValidationException e) {
+ Logger.error("ERROR : ValidationException: signature isn't conform to SAML Signature profile: " + e, e);
+ throw new EIDASSAMLEngineException(e);
+
+ }
+ return sigProfValidator;
+ }
+
+ public <T extends SignableXMLObject> T validateSignature(T signedObject,
+ Collection<X509Certificate> trustedCertificateCollection) throws EIDASSAMLEngineException {
+ List trustedCreds;
+ if (CollectionUtils.isEmpty(trustedCertificateCollection))
+ trustedCreds = getTrustedCredentials();
+
+ else {
+ trustedCreds = CertificateUtil.getListOfCredential(trustedCertificateCollection);
+
+ }
+ return (T) validateSignatureWithCredentials(signedObject, trustedCreds);
+ }
+
+ private <T extends SignableXMLObject> T validateSignatureWithCredentials(T signedObject,
+ List<? extends Credential> trustedCredentialList) throws EIDASSAMLEngineException {
+ Logger.debug("Start signature validation.");
+
+ validateSamlSignatureStructure(signedObject);
+
+ verifyCryptographicSignature(signedObject.getSignature(), trustedCredentialList);
+
+ return signedObject;
+
+ }
+
+ private void verifyCryptographicSignature(Signature signature,
+ List<? extends Credential> trustedCredentialList) throws EIDASSAMLEngineException {
+ String signatureAlgorithmVal = signature.getSignatureAlgorithm();
+ Logger.trace("Key algorithm " + SecurityHelper.getKeyAlgorithmFromURI(signatureAlgorithmVal));
+
+ if (!(isAlgorithmAllowedForVerifying(signatureAlgorithmVal))) {
+ Logger.error("ERROR : the algorithm " + signatureAlgorithmVal + " used by the signature is not allowed");
+ throw new EIDASSAMLEngineException(EidasErrorKey.INVALID_SIGNATURE_ALGORITHM.errorCode());
+
+ }
+
+ X509Credential entityX509Cred = getTrustedCertificate(signature, trustedCredentialList);
+ SignatureValidator sigValidator = new SignatureValidator(entityX509Cred);
+
+ try {
+ sigValidator.validate(signature);
+
+ } catch (ValidationException e) {
+ Logger.error("ERROR : Signature Validation Exception: " + e, e);
+ throw new EIDASSAMLEngineException(e);
+
+ }
+ }
+
+ public boolean isResponseSignAssertions() {
+ return this.responseSignAssertions;
+ }
+
+ static {
+ BouncyCastleBootstrap.bootstrap();
+
+ ALLOWED_ALGORITHMS_FOR_SIGNING = ImmutableSet.of("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
+
+ //Set other algorithms which are not supported by openSAML in default
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1,
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1);
+
+ ALLOWED_ALGORITHMS_FOR_VERIFYING = ImmutableSet.of("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
+
+ //Set other algorithms which are not supported by openSAML in default
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1_MGF1,
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA224_MGF1,
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1,
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384_MGF1,
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1);
+
+ DEFAULT_ALGORITHM_WHITE_LIST = ImmutableSet.of("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
+
+ //Set other algorithms which are not supported by openSAML in default
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1);
+
+ SIGNATURE_TO_DIGEST_ALGORITHM_MAP = ImmutableMap.builder()
+ .put("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "http://www.w3.org/2001/04/xmlenc#sha256")
+ .put("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#sha384")
+ .put("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "http://www.w3.org/2001/04/xmlenc#sha512")
+ .put("http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160",
+ "http://www.w3.org/2001/04/xmlenc#ripemd160")
+ .put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256", "http://www.w3.org/2001/04/xmlenc#sha256")
+ .put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#sha384")
+ .put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512", "http://www.w3.org/2001/04/xmlenc#sha512")
+
+ //Set other algorithms which are not supported by openSAML in default
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1, "http://www.w3.org/2001/04/xmlenc#sha256")
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1, "http://www.w3.org/2001/04/xmlenc#sha512")
+
+ .build();
+ }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java
index 9ad5f0db3..de4f3fc9c 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java
@@ -90,17 +90,21 @@ public class ModifiedEncryptionSW extends KeyStoreSamlEngineEncryption {
*/
@Override
public boolean isEncryptionEnabled(String countryCode) {
- // - encrypt if so configured
+ //encryption is enabled by default in MOA-ID configuration object
try {
AuthConfiguration moaconfig = AuthConfigurationProviderFactory.getInstance();
Boolean useEncryption = moaconfig.getStorkConfig().getCPEPS(countryCode).isXMLSignatureSupported();
- Logger.info(useEncryption ? "using encryption" : "do not use encrpytion");
+ String logResult = useEncryption ? " using encryption" : " do not use encrpytion";
+ Logger.debug("eIDAS respone for country " + countryCode + logResult);
return useEncryption;
+
} catch(NullPointerException | ConfigurationException e) {
Logger.warn("failed to gather information about encryption for countryCode " + countryCode + " - thus, enabling encryption");
if(Logger.isDebugEnabled())
e.printStackTrace();
return true;
+
}
+
}
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java
new file mode 100644
index 000000000..d8fcd1694
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java
@@ -0,0 +1,68 @@
+package at.gv.egovernment.moa.id.auth.modules.eidas.engine;
+
+import java.security.cert.X509Certificate;
+
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.saml2.core.Response;
+
+import at.gv.egovernment.moa.logging.Logger;
+import eu.eidas.auth.commons.EidasErrorKey;
+import eu.eidas.auth.commons.protocol.IAuthenticationRequest;
+import eu.eidas.auth.engine.ProtocolEngine;
+import eu.eidas.auth.engine.configuration.ProtocolConfigurationAccessor;
+import eu.eidas.auth.engine.xml.opensaml.SAMLEngineUtils;
+import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
+
+public class MOAProtocolEngine extends ProtocolEngine {
+
+ public MOAProtocolEngine(ProtocolConfigurationAccessor configurationAccessor) {
+ super(configurationAccessor);
+
+ }
+
+// @Override
+// protected X509Certificate getEncryptionCertificate(String requestIssuer,
+// String destinationCountryCode) throws EIDASSAMLEngineException {
+// if ((StringUtils.isNotBlank(destinationCountryCode)) && (null != getProtocolEncrypter())
+// && (getProtocolEncrypter().isEncryptionEnabled(destinationCountryCode))) {
+// X509Certificate encryptionCertificate = getProtocolProcessor().getEncryptionCertificate(requestIssuer);
+//
+// if (null == encryptionCertificate) {
+// return getProtocolEncrypter().getEncryptionCertificate(destinationCountryCode);
+//
+// }
+// return encryptionCertificate;
+// }
+// return null;
+// }
+//
+// @Override
+// protected Response signResponse(IAuthenticationRequest request, Response response)
+// throws EIDASSAMLEngineException {
+// Response responseToSign = response;
+//
+// if ((null != getProtocolEncrypter()) && (!(SAMLEngineUtils.isErrorSamlResponse(responseToSign)))) {
+// X509Certificate destinationCertificate = getEncryptionCertificate(request.getIssuer(),
+// request.getOriginCountryCode());
+//
+// if (null != destinationCertificate) {
+// responseToSign = getProtocolEncrypter().encryptSamlResponse(responseToSign, destinationCertificate);
+//
+// } else if (getProtocolEncrypter().isEncryptionEnabled(request.getOriginCountryCode())) {
+//// Logger.error(SAML_EXCHANGE,
+//// "BUSINESS EXCEPTION : encryption cannot be performed, no matching certificate for issuer="
+//// + request.getIssuer() + " and country=" + request.getOriginCountryCode());
+//
+// throw new EIDASSAMLEngineException(EidasErrorKey.SAML_ENGINE_INVALID_CERTIFICATE.errorCode(),
+// EidasErrorKey.SAML_ENGINE_INVALID_CERTIFICATE.errorMessage());
+// }
+//
+// } else if (!(SAMLEngineUtils.isErrorSamlResponse(responseToSign))) {
+// checkSendingUnencryptedResponsesAllowed();
+//
+// }
+//
+// Logger.debug("Signing SAML Response.");
+// return ((Response) getSigner().sign(responseToSign));
+// }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java
index a9c4d5d3a..7155040c6 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java
@@ -22,13 +22,10 @@
*/
package at.gv.egovernment.moa.id.auth.modules.eidas.tasks;
-import java.io.ByteArrayOutputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -42,7 +39,6 @@ import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.SingleSignOnService;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-import org.opensaml.xml.util.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -197,7 +193,17 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
}
}
- //build requested attribute set
+ //request
+ if (reqAttrList.isEmpty()) {
+ Logger.info("No attributes requested by OA:" + pendingReq.getOnlineApplicationConfiguration().getPublicURLPrefix()
+ + " --> Request attr:" + Constants.eIDAS_ATTR_PERSONALIDENTIFIER + " by default");
+ AttributeDefinition<?> newAttribute = SAMLEngineUtils.getMapOfAllAvailableAttributes().get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ Builder<?> attrBuilder = AttributeDefinition.builder(newAttribute).required(true);
+ reqAttrList.add(attrBuilder.build());
+
+ }
+
+ //build requested attribute set
ImmutableAttributeMap reqAttrMap = new ImmutableAttributeMap.Builder().putAll(reqAttrList).build();
//build eIDAS AuthnRequest
@@ -211,8 +217,13 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
authnRequestBuilder.nameIdFormat(Constants.eIDAS_REQ_NAMEID_FORMAT);
- //set minimum required eIDAS LoA from OA config
- authnRequestBuilder.levelOfAssurance(LevelOfAssurance.fromString(oaConfig.getQaaLevel()));
+ //set minimum required eIDAS LoA from OA config
+ String LoA = oaConfig.getQaaLevel();
+ if (MiscUtil.isNotEmpty(LoA))
+ authnRequestBuilder.levelOfAssurance(LevelOfAssurance.fromString(oaConfig.getQaaLevel()));
+ else
+ authnRequestBuilder.levelOfAssurance(LevelOfAssurance.HIGH);
+
authnRequestBuilder.levelOfAssuranceComparison(LevelOfAssuranceComparison.MINIMUM);
//set correct SPType for this online application
@@ -234,7 +245,7 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
IRequestMessage authnRequest = engine.generateRequestMessage(authnRequestBuilder.build(), issur);
-
+
//encode AuthnRequest
byte[] token = authnRequest.getMessageBytes();
String SAMLRequest = EidasStringUtil.encodeToBase64(token);
@@ -269,40 +280,6 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
}
}
-
- /**
- * Encode the eIDAS request with Redirect binding
- *
- * @param pendingReq
- * @param authnReqEndpoint
- * @param token
- * @param authnRequest
- * @param response
- * @throws MOAIDException
- */
- private void buildRedirecttBindingRequest(IRequest pendingReq, SingleSignOnService authnReqEndpoint,
- byte[] token, IRequestMessage authnRequest, HttpServletResponse response)
- throws MOAIDException {
-
- //FIXME: implement correct deflat encoding accodring to SAML2 Redirect Binding specification
-
- try {
- ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
- Deflater deflater = new Deflater(Deflater.DEFLATED, true);
- DeflaterOutputStream deflaterStream = new DeflaterOutputStream(bytesOut, deflater);
- deflaterStream.write(token);
- deflaterStream.finish();
- String samlReqBase64 = Base64.encodeBytes(bytesOut.toByteArray(), Base64.DONT_BREAK_LINES);
-
-
-
- } catch (Exception e) {
- Logger.error("eIDAS Redirect-Binding request encoding error: " + e.getMessage());
- throw new MOAIDException("eIDAS.02", new Object[]{e.getMessage()}, e);
-
- }
-
- }
/**
* Encode the eIDAS request with POST binding
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java
index c4b2bfeae..45ba3d64e 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java
@@ -19,12 +19,12 @@ import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.protocols.eidas.validator.eIDASResponseValidator;
import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
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.protocol.IAuthenticationResponse;
-import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance;
import eu.eidas.auth.engine.ProtocolEngineI;
import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
@@ -78,16 +78,8 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask {
// **********************************************************
// ******* MOA-ID specific response validation **********
// **********************************************************
-
- //validate received LoA against minimum required LoA
- LevelOfAssurance reqLoA = LevelOfAssurance.fromString(pendingReq.getOnlineApplicationConfiguration().getQaaLevel());
- LevelOfAssurance respLoA = LevelOfAssurance.fromString(samlResp.getLevelOfAssurance());
- if (respLoA.numericValue() < reqLoA.numericValue()) {
- Logger.error("eIDAS Response LevelOfAssurance is lower than the required! "
- + "(Resp-LoA:" + respLoA.getValue() + " Req-LoA:" + reqLoA.getValue() + ")");
- throw new MOAIDException("eIDAS.14", new Object[]{respLoA.getValue()});
-
- }
+ String spCountry = authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT");
+ eIDASResponseValidator.validateResponse(pendingReq, samlResp, spCountry);
// **********************************************************
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java
index f29d2bb65..47cdb4ade 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java
@@ -95,5 +95,22 @@ public class MOAProtocolEngineFactory extends ProtocolEngineFactory {
}
+// public static ProtocolEngineI createProtocolEngine(String instanceName,
+// ProtocolEngineConfigurationFactory protocolEngineConfigurationFactory,
+// ProtocolProcessorI protocolProcessor, SamlEngineClock samlEngineClock)
+// throws SamlEngineConfigurationException {
+//
+// ProtocolEngineConfiguration preConfiguration = protocolEngineConfigurationFactory
+// .getConfiguration(instanceName);
+//
+// protocolProcessor.configure();
+//
+// ProtocolEngineConfiguration configuration = ProtocolEngineConfiguration.builder(preConfiguration)
+// .protocolProcessor(protocolProcessor).clock(samlEngineClock).build();
+//
+// ProtocolEngineI samlEngine = new MOAProtocolEngine(new FixedProtocolConfigurationAccessor(configuration));
+//
+// return samlEngine;
+// }
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java
index 7d647ff15..a2c6a3ad9 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java
@@ -22,7 +22,6 @@
*/
package at.gv.egovernment.moa.id.auth.modules.eidas.utils;
-import java.util.Locale;
import java.util.regex.Pattern;
import org.apache.commons.collections.CollectionUtils;
@@ -48,6 +47,11 @@ public class MOAWhiteListConfigurator {
}
ImmutableSet.Builder<String> allowed = ImmutableSet.builder();
String[] wlAlgorithms = WHITE_LIST_SPLITTER.split(algorithmWhiteListValue);
+
+ //BugFix: remove newlines from configuration
+ for (int i=0; i<wlAlgorithms.length; i++)
+ wlAlgorithms[i] = StringUtils.trimToNull(KeyValueUtils.removeAllNewlineFromString(wlAlgorithms[i]));
+
if (null != wlAlgorithms && wlAlgorithms.length > 0) {
return getAllowedAlgorithms(defaultWhiteList, allowedValues, ImmutableSet.<String>copyOf(wlAlgorithms));
}
@@ -72,7 +76,11 @@ public class MOAWhiteListConfigurator {
candidateValue = StringUtils.trimToNull(
KeyValueUtils.removeAllNewlineFromString(candidateValue));
if (StringUtils.isNotBlank(candidateValue)) {
- String candidateAlgorithm = StringUtils.lowerCase(candidateValue, Locale.ENGLISH);
+
+ //BUGFIX: eIDAS SAML-engine MPF1 signature schemes problem
+ String candidateAlgorithm = candidateValue;
+ //String candidateAlgorithm = StringUtils.lowerCase(candidateValue, Locale.ENGLISH);
+
if (allowedValues.contains(candidateAlgorithm)) {
allowed.add(candidateValue);
if (!modified && !candidateAlgorithm.equals(candidateValue)) {
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 dd14972e3..8faaf1874 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
@@ -210,10 +210,15 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
addAssertionConsumerService();
}
fillNameIDFormat(spSSODescriptor);
- if (params.getSpEngine() != null) {
- ProtocolEngineI spEngine = params.getSpEngine();
- ((MetadataSignerI) spEngine.getSigner()).signMetadata(spSSODescriptor);
- }
+
+ /**FIXME:
+ * Double signing of SPSSODescribtor is not required
+ */
+// if (params.getSpEngine() != null) {
+// ProtocolEngineI spEngine = params.getSpEngine();
+// ((MetadataSignerI) spEngine.getSigner()).signMetadata(spSSODescriptor);
+// }
+
entityDescriptor.getRoleDescriptors().add(spSSODescriptor);
}
@@ -266,6 +271,8 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
}
idpSSODescriptor.addSupportedProtocol(params.getIdpSamlProtocol());
fillNameIDFormat(idpSSODescriptor);
+
+
if (params.getIdpEngine() != null) {
if (params.getIdpEngine().getProtocolProcessor() != null
&& params.getIdpEngine().getProtocolProcessor().getFormat() == SAMLExtensionFormat.EIDAS10) {
@@ -277,8 +284,13 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
*/
generateSupportedAttributes(idpSSODescriptor, getAllSupportedAttributes());
}
- ProtocolEngineI idpEngine = params.getIdpEngine();
- ((MetadataSignerI) idpEngine.getSigner()).signMetadata(idpSSODescriptor);
+
+
+ /**FIXME:
+ * Double signing of IDPSSODescribtor is not required
+ */
+// ProtocolEngineI idpEngine = params.getIdpEngine();
+// ((MetadataSignerI) idpEngine.getSigner()).signMetadata(idpSSODescriptor);
}
idpSSODescriptor.getSingleSignOnServices().addAll(buildSingleSignOnServicesBindingLocations());
@@ -465,7 +477,7 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
X509Certificate decryptionCertificate = engine.getDecryptionCertificate();
if (null != decryptionCertificate) {
- params.setEncryptionCredential(CertificateUtil.toCredential(decryptionCertificate));
+ params.setSpEncryptionCredential(CertificateUtil.toCredential(decryptionCertificate));
}
params.setSigningCredential(CertificateUtil.toCredential(engine.getSigningCertificate()));
params.setIdpEngine(engine);
@@ -530,7 +542,10 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
Set<String> signatureMethods = EIDASUtil.parseSemicolonSeparatedList(params.getDigestMethods());
Set<String> digestMethods = new HashSet<String>();
for (String signatureMethod : signatureMethods) {
- digestMethods.add(CertificateUtil.validateDigestAlgorithm(signatureMethod));
+
+ //BUGFIX: eIDAS implementation does not allow MGF1 signature schemes
+ digestMethods.add(signatureMethod);
+ //digestMethods.add(CertificateUtil.validateDigestAlgorithm(signatureMethod));
}
for (String digestMethod : digestMethods) {
final DigestMethod dm = (DigestMethod) BuilderFactoryUtil.buildXmlObject(DigestMethod.DEF_ELEMENT_NAME);
@@ -569,7 +584,7 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
generateDigest(eidasExtensions);
if (!StringUtils.isEmpty(params.getSigningMethods())) {
- Set<String> signMethods = EIDASUtil.parseSemicolonSeparatedList(params.getDigestMethods());
+ Set<String> signMethods = EIDASUtil.parseSemicolonSeparatedList(params.getSigningMethods());
for (String signMethod : signMethods) {
final SigningMethod sm =
(SigningMethod) BuilderFactoryUtil.buildXmlObject(SigningMethod.DEF_ELEMENT_NAME);
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 eb50c113f..70135c06f 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
@@ -30,8 +30,8 @@ import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.XMLConfigurator;
import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.config.MOAExtendedSWSigner;
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;
@@ -69,8 +69,8 @@ public class SAMLEngineUtils {
metadataFetcher = new MOAeIDASMetadataProviderDecorator(moaeIDASMetadataProvider);
//set metadata signer
- metadataSigner = new MOASWSigner(configManager);
-
+ metadataSigner = new MOAExtendedSWSigner(configManager);
+
//build eIDAS SAML eninge
ProtocolEngineI engine = MOAProtocolEngineFactory.createProtocolEngine(
Constants.eIDAS_SAML_ENGINE_NAME,
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeProcessingUtils.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeProcessingUtils.java
new file mode 100644
index 000000000..30e1e4505
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeProcessingUtils.java
@@ -0,0 +1,75 @@
+/*
+ * 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.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.data.Trible;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttributeProcessingUtils {
+ public static final String PERSONALIDENIFIER_VALIDATION_PATTERN = "^[A-Z,a-z]{2}/[A-Z,a-z]{2}/.*";
+
+ /**
+ * Validate a eIDAS PersonalIdentifier attribute value
+ * This validation is done according to eIDAS SAML Attribute Profile - Section 2.2.3 Unique Identifier
+ *
+ * @param uniqueID eIDAS attribute value of a unique identifier
+ * @return true if the uniqueID matches to eIDAS to Unique Identifier specification, otherwise false
+ */
+ public static boolean validateEidasPersonalIdentifier(String uniqueID) {
+ Pattern pattern = Pattern.compile(PERSONALIDENIFIER_VALIDATION_PATTERN );
+ Matcher matcher = pattern.matcher(uniqueID);
+ return matcher.matches();
+
+ }
+
+
+ /**
+ * Parse an eIDAS PersonalIdentifier attribute value into it components.
+ * This processing is done according to eIDAS SAML Attribute Profile - Section 2.2.3 Unique Identifier
+ *
+ * @param uniqueID eIDAS attribute value of a unique identifier
+ * @return {@link Trible} that contains:
+ * <br> First : citizen country
+ * <br> Second: destination country
+ * <br> Third : unique identifier
+ * <br> or null if the attribute value has a wrong format
+ */
+ public static Trible<String, String, String> parseEidasPersonalIdentifier(String uniqueID) {
+ if (!validateEidasPersonalIdentifier(uniqueID)) {
+ Logger.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " looks wrong formated. Value:" + ((String)uniqueID));
+ return null;
+
+ }
+ return Trible.newInstance(uniqueID.substring(0, 2), uniqueID.substring(3, 5), uniqueID.substring(6));
+
+ }
+}
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 13e64cdd0..388d65963 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
@@ -25,6 +25,8 @@ package at.gv.egovernment.moa.id.protocols.eidas;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -36,7 +38,6 @@ 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;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -51,6 +52,7 @@ import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASAuthnRequestV
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.MOAIDConstants;
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;
@@ -149,7 +151,8 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
//preProcess eIDAS request
preProcess(req, resp, pendingReq);
- revisionsLogger.logEvent(pendingReq, Constants.eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST);
+ revisionsLogger.logEvent(pendingReq, Constants.eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST,
+ pendingReq.getEidasRequest().getId());
//AuthnRequest needs authentication
pendingReq.setNeedAuthentication(true);
@@ -213,6 +216,11 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
}
+ //check eIDAS node configuration
+ IOAAuthParameters oaConfig = authConfig.getOnlineApplicationParameter(samlReq.getIssuer());
+ if (oaConfig == null)
+ throw new EIDASAuthnRequestProcessingException("eIDAS.08", new Object[]{samlReq.getIssuer()});
+
//validate AssertionConsumerServiceURL against metadata
EntityDescriptor eIDASNodeEntityDesc = new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider)
.getEntityDescriptor(eIDASSamlReq.getIssuer(), SAMLEngineUtils.getMetadataSigner());
@@ -258,8 +266,33 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
}
+ //validate request country-code against eIDAS node config
+ String reqCC = samlReq.getOriginCountryCode();
+ String eIDASTarget = oaConfig.getIdentityLinkDomainIdentifier();
+
+ //validate eIDAS target
+ Pattern pattern = Pattern.compile("^" + at.gv.egovernment.moa.util.Constants.URN_PREFIX_EIDAS
+ + "\\+[A-Z,a-z]{2}\\+[A-Z,a-z]{2}$");
+ Matcher matcher = pattern.matcher(eIDASTarget);
+ if (MiscUtil.isEmpty(eIDASTarget) || !matcher.matches()) {
+ Logger.error("Configuration for eIDAS-node:" + samlReq.getIssuer()
+ + " contains wrong formated eIDAS target:" + eIDASTarget);
+ throw new MOAIDException("config.08", new Object[]{samlReq.getIssuer()});
+
+ } else {
+ String[] splittedTarget = eIDASTarget.split("\\+");
+ if (!splittedTarget[2].equalsIgnoreCase(reqCC)) {
+ Logger.error("Configuration for eIDAS-node:" + samlReq.getIssuer()
+ + " Destination Country from request (" + reqCC
+ + ") does not match to configuration:" + eIDASTarget);
+ throw new MOAIDException("eIDAS.01",
+ new Object[]{"Destination Country from request does not match to configuration"});
+
+ }
+ Logger.debug("CountryCode from request matches eIDAS-node configuration target");
+ }
-
+
//*************************************************
//***** store eIDAS request information *********
//*************************************************
@@ -269,10 +302,6 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
// - 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,
@@ -288,10 +317,6 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
pendingReq.setOAURL(samlReq.getIssuer());
// - memorize OA config
- IOAAuthParameters oaConfig = authConfig.getOnlineApplicationParameter(pendingReq.getOAURL());
- if (oaConfig == null)
- throw new EIDASAuthnRequestProcessingException("eIDAS.08", new Object[]{pendingReq.getOAURL()});
-
pendingReq.setOnlineApplicationConfiguration(oaConfig);
// - memorize service-provider type from eIDAS request
@@ -302,7 +327,7 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
if (MiscUtil.isEmpty(spType))
spType = MetadataUtil.getSPTypeFromMetadata(eIDASNodeEntityDesc);
- if (MiscUtil.isEmpty(spType))
+ if (MiscUtil.isNotEmpty(spType))
Logger.debug("eIDAS request has SPType:" + spType);
else
Logger.info("eIDAS request and eIDAS metadata contains NO 'SPType' element.");
@@ -367,7 +392,7 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
String token = EidasStringUtil.encodeToBase64(eIDASRespMsg.getMessageBytes());
VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
- Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html");
+ Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm");
VelocityContext context = new VelocityContext();
context.put("RelayState", eidasReq.getRemoteRelayState());
@@ -387,7 +412,7 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
Logger.trace("Sending html content : " + new String(writer.getBuffer()));
byte[] content = writer.getBuffer().toString().getBytes("UTF-8");
- response.setContentType(MediaType.TEXT_HTML.getType());
+ response.setContentType(MOAIDConstants.DEFAULT_CONTENT_TYPE_HTML_UTF8);
response.setContentLength(content.length);
response.getOutputStream().write(content);
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 174fa2c17..df96bef12 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
@@ -72,13 +72,19 @@ public class EidasMetaDataRequest implements IAction {
String metadata_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_METADATA;
String sp_return_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_SP_POST;
+ //generate eIDAS metadata
String metaData = generateMetadata(req, metadata_url, sp_return_url);
-
+
+ //write content to response
+ byte[] content = metaData.getBytes("UTF-8");
+ httpResp.setStatus(HttpServletResponse.SC_OK);
+ httpResp.setContentType(MediaType.APPLICATION_XML.toString());
+ httpResp.setContentLength(content.length);
+ httpResp.getOutputStream().write(content);
+
+ //write log if required
Logger.trace(metaData);
-
- httpResp.setContentType(MediaType.APPLICATION_XML.getType());
- httpResp.getWriter().print(metaData);
- httpResp.flushBuffer();
+
} catch (Exception e) {
Logger.error("eIDAS Metadata generation FAILED.", e);
throw new MOAIDException("eIDAS.05", new Object[]{e.getMessage()}, e);
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 22ac37604..2fe52bb4f 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
@@ -34,7 +34,6 @@ 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;
import com.google.common.collect.ImmutableSet;
@@ -44,11 +43,14 @@ import at.gv.egovernment.moa.id.auth.frontend.velocity.VelocityProvider;
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.utils.SimpleEidasAttributeGenerator;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.eIDASAttributeProcessingUtils;
+import at.gv.egovernment.moa.id.commons.MOAIDConstants;
import at.gv.egovernment.moa.id.commons.api.IRequest;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
import at.gv.egovernment.moa.id.data.IAuthData;
import at.gv.egovernment.moa.id.data.SLOInformationImpl;
import at.gv.egovernment.moa.id.data.SLOInformationInterface;
+import at.gv.egovernment.moa.id.data.Trible;
import at.gv.egovernment.moa.id.moduls.IAction;
import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator;
import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonFullNameAttributeBuilder;
@@ -121,12 +123,28 @@ public class eIDASAuthenticationRequest implements IAction {
newValue = authData.getBPK();
isUniqueID = true;
+ //generate eIDAS conform 'PersonalIdentifier' attribute
+ if (!eIDASAttributeProcessingUtils.validateEidasPersonalIdentifier(newValue)) {
+ Logger.debug("preCalculated PersonalIdentifier does not include eIDAS conform prefixes ... add prefix now");
+ if (MiscUtil.isEmpty(authData.getBPKType())
+ || !authData.getBPKType().startsWith(at.gv.egovernment.moa.util.Constants.URN_PREFIX_EIDAS)) {
+ Logger.error("BPKType is empty or does not start with eIDAS bPKType prefix! bPKType:" + authData.getBPKType());
+ throw new MOAIDException("builder.08", new Object[]{"Suspect bPKType for eIDAS identifier generation"});
+
+ }
+
+ String prefix = authData.getBPKType().substring(at.gv.egovernment.moa.util.Constants.URN_PREFIX_EIDAS.length() + 1);
+ newValue = prefix.replaceAll("\\+", "/") + "/" + newValue;
+
+ }
+
//generate a transient unique identifier if it is requested
String reqNameIDFormat = eidasRequest.getEidasRequest().getNameIdFormat();
if (MiscUtil.isNotEmpty(reqNameIDFormat)
&& reqNameIDFormat.equals(SamlNameIdFormat.TRANSIENT.getNameIdFormat()))
newValue = generateTransientNameID(newValue);
-
+
+
subjectNameID = newValue;
break;
case Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER:
@@ -145,8 +163,14 @@ public class eIDASAuthenticationRequest implements IAction {
}
- if(MiscUtil.isEmpty(newValue)) {
- Logger.info("eIDAS Attr:" + attr.getNameUri() + " is not available.");
+ if(MiscUtil.isEmpty(newValue)) {
+ if (attr.isRequired()) {
+ Logger.info("eIDAS Attr:" + attr.getNameUri() + " is marked as 'Required' but not available.");
+ throw new MOAIDException("eIDAS.15", new Object[]{attr.getFriendlyName()});
+
+ } else
+ Logger.info("eIDAS Attr:" + attr.getNameUri() + " is not available.");
+
} else {
//set uniqueIdentifier attribute, because eIDAS SAMLEngine use this flag to select the
@@ -228,12 +252,13 @@ public class eIDASAuthenticationRequest implements IAction {
}
- revisionsLogger.logEvent(req, Constants.eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST);
+ revisionsLogger.logEvent(req, Constants.eIDAS_REVERSIONSLOG_IDP_AUTHRESPONSE,
+ eIDASRespMsg.getResponse().getId());
// send the response
try {
VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
- Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html");
+ Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm");
VelocityContext context = new VelocityContext();
context.put("RelayState", eidasRequest.getRemoteRelayState());
@@ -253,7 +278,7 @@ public class eIDASAuthenticationRequest implements IAction {
Logger.trace("Sending html content : " + new String(writer.getBuffer()));
byte[] content = writer.getBuffer().toString().getBytes("UTF-8");
- httpResp.setContentType(MediaType.TEXT_HTML.getType());
+ httpResp.setContentType(MOAIDConstants.DEFAULT_CONTENT_TYPE_HTML_UTF8);
httpResp.setContentLength(content.length);
httpResp.getOutputStream().write(content);
@@ -295,12 +320,20 @@ public class eIDASAuthenticationRequest implements IAction {
private String generateTransientNameID(String nameID) {
- String random = Random.nextLongRandom();
+ //extract source-country and destination country from persistent identifier
+ Trible<String, String, String> split = eIDASAttributeProcessingUtils.parseEidasPersonalIdentifier(nameID);
+ if (split == null) {
+ Logger.error("eIDAS 'PersonalIdentifier' has a wrong format. There had to be a ERROR in implementation!!!!");
+ throw new IllegalStateException("eIDAS 'PersonalIdentifier' has a wrong format. There had to be a ERROR in implementation!!!!");
+
+ }
+ //build correct formated transient identifier
+ String random = Random.nextLongRandom();
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
- byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1"));
- return Base64Utils.encode(hash);
+ byte[] hash = md.digest((split.getThird() + random).getBytes("ISO-8859-1"));
+ return split.getFirst() + "/" + split.getSecond() + "/" + Base64Utils.encode(hash);
} catch (Exception e) {
Logger.error("Can not generate transient personal identifier!", e);
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/validator/eIDASResponseValidator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/validator/eIDASResponseValidator.java
new file mode 100644
index 000000000..f0527bc5e
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/validator/eIDASResponseValidator.java
@@ -0,0 +1,130 @@
+/*
+ * 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.protocols.eidas.validator;
+
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.eIDASAttributeProcessingUtils;
+import at.gv.egovernment.moa.id.commons.api.IRequest;
+import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
+import at.gv.egovernment.moa.id.data.Trible;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import eu.eidas.auth.commons.protocol.IAuthenticationResponse;
+import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASResponseValidator {
+
+
+ public static void validateResponse(IRequest pendingReq, IAuthenticationResponse samlResp, String spCountry) throws MOAIDException {
+
+ /*-----------------------------------------------------|
+ * validate received LoA against minimum required LoA |
+ *_____________________________________________________|
+ */
+ LevelOfAssurance reqLoA = LevelOfAssurance.fromString(pendingReq.getOnlineApplicationConfiguration().getQaaLevel());
+ LevelOfAssurance respLoA = LevelOfAssurance.fromString(samlResp.getLevelOfAssurance());
+ if (respLoA.numericValue() < reqLoA.numericValue()) {
+ Logger.error("eIDAS Response LevelOfAssurance is lower than the required! "
+ + "(Resp-LoA:" + respLoA.getValue() + " Req-LoA:" + reqLoA.getValue() + ")");
+ throw new MOAIDException("eIDAS.14", new Object[]{respLoA.getValue()});
+
+ }
+
+ /*-----------------------------------------------------|
+ * validate 'PersonalIdentifier' attribute |
+ *_____________________________________________________|
+ */
+ String respCC = samlResp.getCountry();
+ Object personalIdObj = samlResp.getAttributes().getFirstValue(
+ SAMLEngineUtils.getMapOfAllAvailableAttributes().get(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER));
+
+ //check attribute type
+ if (personalIdObj == null || !(personalIdObj instanceof String))
+ Logger.warn("eIDAS Response include NO 'PersonalIdentifier' attriubte "
+ + ".... That can be a BIG problem in further processing steps");
+
+ else {
+ //validate attribute value format
+ Trible<String, String, String> split =
+ eIDASAttributeProcessingUtils.parseEidasPersonalIdentifier((String)personalIdObj);
+ if (split == null) {
+ throw new MOAIDException("eIDAS.16",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Wrong identifier format"});
+
+ } else {
+ //validation according to eIDAS SAML Attribute Profile, Section 2.2.3
+ if (MiscUtil.isEmpty(split.getSecond())) {
+ Logger.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes NO destination country. Value:" + ((String)personalIdObj));
+ throw new MOAIDException("eIDAS.16",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "No or empty destination country"});
+
+ }
+ if (!split.getSecond().equalsIgnoreCase(spCountry)) {
+ Logger.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes wrong destination country. Value:" + ((String)personalIdObj)
+ + " SP-Country:" + spCountry);
+ throw new MOAIDException("eIDAS.16",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Destination country does not match to SP country"});
+
+ }
+
+ if (MiscUtil.isEmpty(split.getFirst())) {
+ Logger.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes NO citizen country. Value:" + ((String)personalIdObj));
+ throw new MOAIDException("eIDAS.16",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "No or empty citizen country"});
+
+ }
+ if (!split.getFirst().equalsIgnoreCase(respCC)) {
+ Logger.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes a citizen country that does not match to eIDAS Response node. "
+ + " Value:" + ((String)personalIdObj)
+ + " Response-Node Country:" + respCC);
+ throw new MOAIDException("eIDAS.16",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Citizen country does not match to eIDAS-node country that generates the response"});
+
+ }
+ }
+ }
+
+
+
+ }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm
index 3bd225b00..0535d48b6 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm
@@ -7,7 +7,7 @@
## SAMLRequest - String - the Base64 encoded SAML Request
## SAMLResponse - String - the Base64 encoded SAML Response
## Contains target attribute to delegate PEPS authentication out of iFrame
-
+<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>