aboutsummaryrefslogtreecommitdiff
path: root/id/server
diff options
context:
space:
mode:
Diffstat (limited to 'id/server')
-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.java4
-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/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/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/ServiceProviderSpecificGUIFormBuilderConfiguration.java8
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java2
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java50
-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/eIDASAttributeProcessingUtils.java75
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java47
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java47
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/validator/eIDASResponseValidator.java130
18 files changed, 354 insertions, 91 deletions
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 99e4b4cce..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
@@ -96,7 +96,7 @@ public class STORKConfig implements IStorkConfig {
new CPEPS(storkCPEPSProps.get(listCounter + "." + MOAIDConfigurationConstants.GENERAL_AUTH_STORK_CPEPS_LIST_COUNTRY),
new URL(storkCPEPSProps.get(listCounter + "." + MOAIDConfigurationConstants.GENERAL_AUTH_STORK_CPEPS_LIST_URL)),
enableAssertionEncryption);
- cpepsMap.put(moacpep.getCountryCode(), moacpep);
+ cpepsMap.put(moacpep.getFullCountryCode(), moacpep);
} catch (MalformedURLException e) {
Logger.warn("CPEPS URL " +
@@ -167,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/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/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/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/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 6cb4d6add..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
@@ -98,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(
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 0eb067c5a..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
@@ -274,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/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 aefae939b..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;
@@ -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.");
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 97241af6a..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
@@ -43,12 +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,7 +252,8 @@ 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 {
@@ -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"});
+
+ }
+ }
+ }
+
+
+
+ }
+}