aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorThomas <>2022-08-25 14:59:03 +0200
committerThomas <>2022-08-25 14:59:03 +0200
commitfd692be28186154ec5d217dfa35dbae45e5e0166 (patch)
treec68e475d1d09985a9084221e9aaf2d45f630da8d /modules
parent21b47ed477a52688918ff03bea64436a6ce621b8 (diff)
downloadNational_eIDAS_Gateway-fd692be28186154ec5d217dfa35dbae45e5e0166.tar.gz
National_eIDAS_Gateway-fd692be28186154ec5d217dfa35dbae45e5e0166.tar.bz2
National_eIDAS_Gateway-fd692be28186154ec5d217dfa35dbae45e5e0166.zip
feat(eidas): add support for new IDA AuthBlock format
The ID Austria system changes the format of technical AuthBlock with Frontend/Backend interface-specification v1.1.0
Diffstat (limited to 'modules')
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java210
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidLegacyTest.java459
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java18
-rw-r--r--modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java2
4 files changed, 600 insertions, 89 deletions
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java
index 098e76ce..1998fa85 100644
--- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java
@@ -1,5 +1,6 @@
package at.asitplus.eidas.specific.modules.auth.eidas.v2.service;
+import java.io.Serializable;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
@@ -44,7 +45,7 @@ import lombok.extern.slf4j.Slf4j;
/**
* Service to build and sign AuthBlock's for E-ID system.
- *
+ *
* @author tlenz
*
*/
@@ -55,157 +56,206 @@ public class AuthBlockSigningService {
private static final String KEYSTORE_FRIENDLYNAME = "AuthBlock_Signing";
private static ObjectMapper mapper = new ObjectMapper();
-
+
@Autowired
IConfiguration basicConfig;
-
+
@Autowired
EaafKeyStoreFactory keyStoreFactory;
-
private Pair<KeyStore, Provider> keyStore;
-
+
/**
- * Build and sign an AuthBlock for E-ID system.
- *
+ * Build and sign an AuthBlock for E-ID system.
+ *
* @param pendingReq data that should be added into AuthBlock
* @return serialized JWS
- * @throws JsonProcessingException In case of a AuthBlock generation error
- * @throws JoseException In case of a JWS signing error
- * @throws EaafException In case of a KeyStore or Key error
+ * @throws JsonProcessingException In case of a AuthBlock generation error
+ * @throws JoseException In case of a JWS signing error
+ * @throws EaafException In case of a KeyStore or Key error
*/
- public String buildSignedAuthBlock(IRequest pendingReq)
+ public String buildSignedAuthBlock(IRequest pendingReq)
throws JsonProcessingException, EaafException, JoseException {
-
- //TODO: set Challenge to SAML2 requestId to create link between authentication request and authBlock
-
+
+ // TODO: set Challenge to SAML2 requestId to create link between authentication
+ // request and authBlock
+
// build AuthBlock
- EidasAuchBlock authBlock = new EidasAuchBlock();
- authBlock.setChallenge(UUID.randomUUID().toString());
- authBlock.setTimestamp(LocalDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS));
- authBlock.setUniqueId(pendingReq.getRawData(MsEidasNodeConstants.DATA_REQUESTERID, String.class));
- authBlock.setPiiTransactionId(pendingReq.getUniquePiiTransactionIdentifier());
-
- //set Binding PublicKey if available
- Object bindingPubKey = pendingReq.getRawData(MsEidasNodeConstants.EID_BINDING_PUBLIC_KEY_NAME);
- if (bindingPubKey instanceof String) {
- authBlock.setBindingPublicKey((String) bindingPubKey);
-
- }
-
- String jwsPayload = mapper.writeValueAsString(authBlock);
+ final String jwsPayload = mapper.writeValueAsString(buildAuthBlock(pendingReq));
log.debug("Building and sign authBlock with data: {}", jwsPayload);
-
- //sign JWS
- return JoseUtils
- .createSignature(keyStore, getKeyAlias(), getKeyPassword(), jwsPayload, false,
- KEYSTORE_FRIENDLYNAME);
+
+ // sign JWS
+ return JoseUtils.createSignature(
+ keyStore, getKeyAlias(), getKeyPassword(), jwsPayload, false, KEYSTORE_FRIENDLYNAME);
+
+ }
+
+ private Serializable buildAuthBlock(IRequest pendingReq) {
+ if (basicConfig.getBasicConfigurationBoolean(
+ MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_LEGACY_USE, false)) {
+ final EidasAuchBlockV1 authBlock = new EidasAuchBlockV1();
+ authBlock.setChallenge(UUID.randomUUID().toString());
+ authBlock.setTimestamp(LocalDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS));
+ authBlock.setUniqueId(pendingReq.getRawData(MsEidasNodeConstants.DATA_REQUESTERID, String.class));
+ authBlock.setPiiTransactionId(pendingReq.getUniquePiiTransactionIdentifier());
+
+ // set Binding PublicKey if available
+ final Object bindingPubKey = pendingReq.getRawData(MsEidasNodeConstants.EID_BINDING_PUBLIC_KEY_NAME);
+ if (bindingPubKey instanceof String) {
+ authBlock.setBindingPublicKey((String) bindingPubKey);
+
+ }
+ return authBlock;
+
+ } else {
+ final EidasAuchBlockV2 authBlock = new EidasAuchBlockV2();
+ authBlock.setChallenge(UUID.randomUUID().toString());
+ authBlock.setTimestamp(LocalDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS));
+
+ // set Binding PublicKey if available
+ final Object bindingPubKey = pendingReq.getRawData(MsEidasNodeConstants.EID_BINDING_PUBLIC_KEY_NAME);
+ if (bindingPubKey instanceof String) {
+ authBlock.setBindingPublicKey((String) bindingPubKey);
+
+ }
+ return authBlock;
+
+ }
}
-
/**
* Get the Base64 encoded PublicKey that is used to sign the AuthBlock.
- *
+ *
* @return Base64 encoded PublicKey
* @throws EaafKeyAccessException In case of an unknown or invalid key
*/
- public String getBase64EncodedPublicKey() throws EaafKeyAccessException {
- Pair<Key, X509Certificate[]> keyPair = EaafKeyStoreUtils.getPrivateKeyAndCertificates(
- keyStore.getFirst(), getKeyAlias(), getKeyPassword(), true, KEYSTORE_FRIENDLYNAME);
+ public String getBase64EncodedPublicKey() throws EaafKeyAccessException {
+ final Pair<Key, X509Certificate[]> keyPair = EaafKeyStoreUtils.getPrivateKeyAndCertificates(
+ keyStore.getFirst(), getKeyAlias(), getKeyPassword(), true, KEYSTORE_FRIENDLYNAME);
return Base64.getEncoder().encodeToString(keyPair.getSecond()[0].getPublicKey().getEncoded());
-
+
}
@PostConstruct
- private void initialize() throws KeyStoreException, EaafException {
+ private void initialize() throws KeyStoreException, EaafException {
log.debug("Initializing AuthBlock signing service ... ");
- // read Connector wide config data TODO connector wide!
- String keyStoreName = basicConfig
+ // read Connector wide config data TODO connector wide!
+ final String keyStoreName = basicConfig
.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_NAME);
- String keyStorePw = basicConfig
+ final String keyStorePw = basicConfig
.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PASSWORD);
- String keyStorePath = basicConfig
+ final String keyStorePath = basicConfig
.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PATH);
- String keyStoreType = basicConfig
+ final String keyStoreType = basicConfig
.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_TYPE);
-
- //build new KeyStore configuration
- KeyStoreConfiguration keyStoreConfiguration = new KeyStoreConfiguration();
+ // build new KeyStore configuration
+ final KeyStoreConfiguration keyStoreConfiguration = new KeyStoreConfiguration();
keyStoreConfiguration.setFriendlyName(KEYSTORE_FRIENDLYNAME);
-
+
keyStoreConfiguration.setSoftKeyStoreFilePath(keyStorePath);
keyStoreConfiguration.setSoftKeyStorePassword(keyStorePw);
- keyStoreConfiguration.setKeyStoreType(KeyStoreConfiguration.KeyStoreType.fromString(keyStoreType));
+ keyStoreConfiguration.setKeyStoreType(KeyStoreConfiguration.KeyStoreType.fromString(keyStoreType));
keyStoreConfiguration.setKeyStoreName(keyStoreName);
-
- //validate KeyStore configuration
+
+ // validate KeyStore configuration
keyStoreConfiguration.validate();
-
- //validate key alias
+
+ // validate key alias
if (StringUtils.isEmpty(getKeyAlias())) {
- throw new EaafConfigurationException("config.08",
- new Object[] {MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_ALIAS});
-
+ throw new EaafConfigurationException("config.08",
+ new Object[] { MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_ALIAS });
+
}
-
- //build new KeyStore based on configuration
- keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfiguration);
-
- //check if Key is accessible
+
+ // build new KeyStore based on configuration
+ keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfiguration);
+
+ // check if Key is accessible
EaafKeyStoreUtils.getPrivateKeyAndCertificates(
keyStore.getFirst(), getKeyAlias(), getKeyPassword(), true, KEYSTORE_FRIENDLYNAME);
-
- log.info("AuthBlock signing-service successful initialized");
-
- }
-
+
+ log.info("AuthBlock signing-service successful initialized {}",
+ basicConfig.getBasicConfigurationBoolean(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_LEGACY_USE, false)
+ ? " in legacy mode"
+ : "");
+
+ }
+
private char[] getKeyPassword() {
- final String value = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_PASSWORD);
+ final String value = basicConfig.getBasicConfiguration(
+ MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_PASSWORD);
if (value != null) {
return value.trim().toCharArray();
}
return null;
-
- }
+ }
private String getKeyAlias() {
return basicConfig
.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_ALIAS);
-
+
}
-
+
/**
* Technical AuthBlock for eIDAS Authentication.
- *
+ *
* @author tlenz
*
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
- private static class EidasAuchBlock {
+ @Deprecated
+ private static class EidasAuchBlockV1 implements Serializable {
+
+ private static final long serialVersionUID = 8437172632081476257L;
@JsonProperty("challenge")
private String challenge;
-
+
@JsonProperty("timestamp")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC")
private LocalDateTime timestamp;
-
+
@JsonProperty("appId")
private String uniqueId;
-
+
@JsonProperty("piiTransactionId")
private String piiTransactionId;
-
+
+ @JsonProperty("bindingPublicKey")
+ private String bindingPublicKey;
+
+ }
+
+ /**
+ * AuthBlock for Binding Authentication.
+ *
+ * @author tlenz
+ *
+ */
+ @Data
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public class EidasAuchBlockV2 implements Serializable {
+
+ private static final long serialVersionUID = -2013435642666124497L;
+
+ @JsonProperty("challenge")
+ private String challenge;
+
+ @JsonProperty("issuedAt")
+ @JsonSerialize(using = LocalDateTimeSerializer.class)
+ @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC")
+ private LocalDateTime timestamp;
+
@JsonProperty("bindingPublicKey")
private String bindingPublicKey;
-
+
}
-
}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidLegacyTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidLegacyTest.java
new file mode 100644
index 00000000..a7d625f5
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidLegacyTest.java
@@ -0,0 +1,459 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks;
+
+import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import java.net.URISyntaxException;
+import java.security.KeyStore;
+import java.security.Provider;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.jose4j.jwa.AlgorithmConstraints;
+import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
+import org.jose4j.jws.AlgorithmIdentifiers;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.skjolber.mockito.soap.SoapServiceRule;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.ICcSpecificEidProcessingService;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils.JwsResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.MatchingTaskUtils;
+import at.asitplus.eidas.specific.modules.core.eidas.EidasConstants;
+import at.asitplus.eidas.specific.modules.core.eidas.service.EidasAttributeRegistry;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.IRequestStorage;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeValue;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap.Builder;
+import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress;
+import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse;
+import lombok.val;
+import szrservices.GetIdentityLinkEidasResponse;
+import szrservices.PersonInfoType;
+import szrservices.SZR;
+import szrservices.SZRException_Exception;
+import szrservices.SignContentEntry;
+import szrservices.SignContentResponseType;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+public class CreateIdentityLinkTaskEidLegacyTest {
+
+ @Autowired(required = true)
+ private CreateIdentityLinkTask task;
+
+ @Autowired(required = true)
+ private MsConnectorDummyConfigMap basicConfig;
+ @Autowired
+ protected EidasAttributeRegistry attrRegistry;
+
+ @Autowired
+ EaafKeyStoreFactory keyStoreFactory;
+
+ @Autowired
+ ICcSpecificEidProcessingService eidPostProcessor;
+
+ @Autowired
+ private IRequestStorage requestStorage;
+
+ final ExecutionContext executionContext = new ExecutionContextImpl();
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private TestRequestImpl pendingReq;
+ private DummySpConfiguration oaParam;
+ private SZR szrMock;
+
+ private static final String PW = "f/+saJBc3a}*/T^s";
+ private static final String ALIAS = "connectorkeypair";
+
+ private static final List<String> BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING = Collections.unmodifiableList(Arrays
+ .asList(AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256,
+ AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512, AlgorithmIdentifiers.RSA_PSS_USING_SHA256,
+ AlgorithmIdentifiers.RSA_PSS_USING_SHA512));
+
+ private static ObjectMapper mapper = new ObjectMapper();
+
+ private AuthenticationResponse response;
+ private MatchedPersonResult matchingInfos;
+
+ @Rule
+ public final SoapServiceRule soap = SoapServiceRule.newInstance();
+
+ /**
+ * jUnit test set-up.
+ * @throws EidasAttributeException
+ * @throws EidPostProcessingException
+ */
+ @Before
+ public void setUp() throws EaafStorageException, URISyntaxException, EidPostProcessingException, EidasAttributeException {
+
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.authblock.use.legacy.version", "true");
+
+ final Map<String, String> spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true");
+ oaParam = new DummySpConfiguration(spConfig, basicConfig);
+ pendingReq = new TestRequestImpl();
+
+ response = buildDummyAuthResponse(false);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);
+
+ final Map<String, Object> eidasAttributes = convertEidasAttrToSimpleMap(
+ response.getAttributes().getAttributeMap());
+ final SimpleEidasData eidData = eidPostProcessor.postProcess(eidasAttributes);
+ MatchingTaskUtils.storeInitialEidasData(pendingReq, eidData);
+
+ matchingInfos = MatchedPersonResult.builder()
+ .bpk(RandomStringUtils.randomAlphabetic(5))
+ .givenName(eidData.getGivenName())
+ .familyName(eidData.getFamilyName())
+ .dateOfBirth(eidData.getDateOfBirth())
+ .countryCode(eidData.getCitizenCountryCode())
+ .build();
+ MatchingTaskUtils.storeFinalMatchingResult(pendingReq, matchingInfos);
+
+ pendingReq.setSpConfig(oaParam);
+ pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue());
+ pendingReq.setAuthUrl("http://test.com/");
+ pendingReq.setTransactionId("avaasbav");
+ pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10));
+
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "XX");
+ executionContext.put(EaafConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT, true);
+
+ szrMock = soap.mock(SZR.class, "http://localhost:1234/demoszr");
+ }
+
+ @Test
+ public void successfulProcessWithDeInfos() throws Exception {
+ //initialize test
+ response = buildDummyAuthResponse(true);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);
+
+ SimpleEidasData eidData = eidPostProcessor.postProcess(
+ convertEidasAttrToSimpleMap(response.getAttributes().getAttributeMap()));
+ MatchingTaskUtils.storeInitialEidasData(pendingReq, eidData);
+
+ matchingInfos = MatchedPersonResult.builder()
+ .bpk(RandomStringUtils.randomAlphabetic(5))
+ .givenName(eidData.getGivenName())
+ .familyName(eidData.getFamilyName())
+ .dateOfBirth(eidData.getDateOfBirth())
+ .countryCode(eidData.getCitizenCountryCode())
+ .build();
+ MatchingTaskUtils.storeFinalMatchingResult(pendingReq, matchingInfos);
+
+ String vsz = RandomStringUtils.randomNumeric(10);
+ when(szrMock.getStammzahlEncrypted(any(), any())).thenReturn(vsz);
+ SignContentResponseType signContentResp = new SignContentResponseType();
+ final SignContentEntry signContentEntry = new SignContentEntry();
+ signContentEntry.setValue(RandomStringUtils.randomAlphanumeric(10));
+ signContentResp.getOut().add(signContentEntry);
+ when(szrMock.signContent(any(), any(), any())).thenReturn(signContentResp);
+
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ // check if pendingRequest was stored
+ IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedPendingReq);
+
+ //check data in session
+ final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertNotNull("AuthProcessData", authProcessData);
+ Assert.assertNotNull("eidasBind", authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+
+ String authBlock = authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ Assert.assertNotNull("AuthBlock", authBlock);
+
+ Assert.assertTrue("EID process", authProcessData.isEidProcess());
+ Assert.assertTrue("foreigner process", authProcessData.isForeigner());
+ Assert.assertEquals("EID-ISSUING_NATION", "LU",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class));
+
+ // check authblock signature
+ final AlgorithmConstraints constraints = new AlgorithmConstraints(ConstraintType.PERMIT,
+ BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.toArray(new String[BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.size()]));
+ Pair<KeyStore, Provider> keyStore = getKeyStore();
+ X509Certificate[] trustedCerts = EaafKeyStoreUtils
+ .getPrivateKeyAndCertificates(keyStore.getFirst(), ALIAS, PW.toCharArray(), true, "junit").getSecond();
+ JwsResult result = JoseUtils.validateSignature(authBlock, Arrays.asList(trustedCerts), constraints);
+ Assert.assertTrue("AuthBlock not valid", result.isValid());
+ JsonNode authBlockJson = mapper.readTree(result.getPayLoad());
+ Assert.assertNotNull("deserialized AuthBlock", authBlockJson);
+
+ Assert.assertNotNull("no piiTransactionId in pendingRequesdt",
+ storedPendingReq.getUniquePiiTransactionIdentifier());
+ Assert.assertFalse("'challenge' is null", authBlockJson.get("challenge").asText().isEmpty());
+ Assert.assertEquals("piiTransactionId", storedPendingReq.getUniquePiiTransactionIdentifier(),
+ authBlockJson.get("piiTransactionId").asText());
+ Assert.assertEquals("appId", randomTestSp, authBlockJson.get("appId").asText());
+ Assert.assertFalse("'timestamp' is null", authBlockJson.get("timestamp").asText().isEmpty());
+ Assert.assertFalse("binding pubKey", authBlockJson.has("bindingPublicKey"));
+
+ }
+
+
+
+ @Test
+ public void successfulProcessWithDataFromMatching() throws Exception {
+ //initialize test
+ String vsz = RandomStringUtils.randomNumeric(10);
+ when(szrMock.getStammzahlEncrypted(any(), any())).thenReturn(vsz);
+ SignContentResponseType signContentResp = new SignContentResponseType();
+ final SignContentEntry signContentEntry = new SignContentEntry();
+ signContentEntry.setValue(RandomStringUtils.randomAlphanumeric(10));
+ signContentResp.getOut().add(signContentEntry);
+
+ when(szrMock.signContent(any(), any(), any())).thenReturn(signContentResp);
+
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ String bindingPubKey = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.EID_BINDING_PUBLIC_KEY_NAME, bindingPubKey);
+
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+
+ //validate state
+ // check if pendingRequest was stored
+ IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedPendingReq);
+
+ //check data in session
+ final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertNotNull("AuthProcessData", authProcessData);
+ Assert.assertNotNull("eidasBind", authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+
+ // check authblock signature
+ String authBlock = authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ Assert.assertNotNull("AuthBlock", authBlock);
+
+ final AlgorithmConstraints constraints = new AlgorithmConstraints(ConstraintType.PERMIT,
+ BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.toArray(new String[BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.size()]));
+ Pair<KeyStore, Provider> keyStore = getKeyStore();
+ X509Certificate[] trustedCerts = EaafKeyStoreUtils
+ .getPrivateKeyAndCertificates(keyStore.getFirst(), ALIAS, PW.toCharArray(), true, "junit").getSecond();
+ JwsResult result = JoseUtils.validateSignature(authBlock, Arrays.asList(trustedCerts), constraints);
+ Assert.assertTrue("AuthBlock not valid", result.isValid());
+ JsonNode authBlockJson = mapper.readTree(result.getPayLoad());
+ Assert.assertNotNull("deserialized AuthBlock", authBlockJson);
+
+ Assert.assertNotNull("no piiTransactionId in pendingRequesdt",
+ storedPendingReq.getUniquePiiTransactionIdentifier());
+ Assert.assertFalse("'challenge' is null", authBlockJson.get("challenge").asText().isEmpty());
+ Assert.assertEquals("piiTransactionId", storedPendingReq.getUniquePiiTransactionIdentifier(),
+ authBlockJson.get("piiTransactionId").asText());
+ Assert.assertEquals("appId", randomTestSp, authBlockJson.get("appId").asText());
+ Assert.assertFalse("'timestamp' is null", authBlockJson.get("timestamp").asText().isEmpty());
+
+ }
+
+ private Pair<KeyStore, Provider> getKeyStore() throws EaafException {
+ // read Connector wide config data TODO connector wide!
+ String keyStoreName = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_NAME);
+ String keyStorePw = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PASSWORD);
+ String keyStorePath = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PATH);
+ String keyStoreType = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_TYPE);
+
+
+ //build new KeyStore configuration
+ KeyStoreConfiguration keyStoreConfiguration = new KeyStoreConfiguration();
+ keyStoreConfiguration.setFriendlyName("jUnit test");
+
+ keyStoreConfiguration.setSoftKeyStoreFilePath(keyStorePath);
+ keyStoreConfiguration.setSoftKeyStorePassword(keyStorePw);
+ keyStoreConfiguration.setKeyStoreType(KeyStoreConfiguration.KeyStoreType.fromString(keyStoreType));
+ keyStoreConfiguration.setKeyStoreName(keyStoreName);
+
+ //build new KeyStore based on configuration
+ return keyStoreFactory.buildNewKeyStore(keyStoreConfiguration);
+
+ }
+
+ @Nonnull
+ private void setSzrResponseIdentityLink(String responseXmlPath) throws JAXBException, SZRException_Exception {
+ final JAXBContext jaxbContext = JAXBContext
+ .newInstance(szrservices.ObjectFactory.class, org.w3._2001._04.xmldsig_more.ObjectFactory.class,
+ org.w3._2000._09.xmldsig.ObjectFactory.class,
+ at.gv.e_government.reference.namespace.persondata._20020228.ObjectFactory.class);
+ final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+ final GetIdentityLinkEidasResponse szrResponse = (GetIdentityLinkEidasResponse) jaxbUnmarshaller
+ .unmarshal(this.getClass().getResourceAsStream(responseXmlPath));
+ org.mockito.Mockito.when(szrMock.getIdentityLinkEidas(any(PersonInfoType.class))).thenReturn(szrResponse.getGetIdentityLinkReturn());
+
+ }
+
+ @Nonnull
+ private AuthenticationResponse buildDummyAuthResponse(boolean withAll) throws URISyntaxException {
+ return buildDummyAuthResponse(withAll, false);
+
+ }
+
+ @Nonnull
+ private AuthenticationResponse buildDummyAuthResponse(boolean withAll, boolean withEmpty) throws URISyntaxException {
+ final AttributeDefinition attributeDef = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+ final AttributeDefinition attributeDef2 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME).first();
+ final AttributeDefinition attributeDef3 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME).first();
+ final AttributeDefinition attributeDef4 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ EidasConstants.eIDAS_ATTR_DATEOFBIRTH).first();
+ final AttributeDefinition attributeDef5 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ EidasConstants.eIDAS_ATTR_PLACEOFBIRTH).first();
+ final AttributeDefinition attributeDef6 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ EidasConstants.eIDAS_ATTR_BIRTHNAME).first();
+
+ final Builder attributeMap = ImmutableAttributeMap.builder();
+ attributeMap.put(attributeDef, "LU/AT/" + RandomStringUtils.randomNumeric(64));
+ attributeMap.put(attributeDef2, RandomStringUtils.randomAlphabetic(10));
+ attributeMap.put(attributeDef3, RandomStringUtils.randomAlphabetic(10));
+ attributeMap.put(attributeDef4, "2001-01-01");
+ if (withAll) {
+ if (withEmpty) {
+ attributeMap.put(attributeDef5, Collections.emptySet());
+
+ } else {
+ attributeMap.put(attributeDef5, RandomStringUtils.randomAlphabetic(10));
+
+ }
+ attributeMap.put(attributeDef6, RandomStringUtils.randomAlphabetic(10));
+
+ }
+
+ val b = new AuthenticationResponse.Builder();
+ return b.id("_".concat(Random.nextHexRandom16()))
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .subject(RandomStringUtils.randomAlphabetic(10))
+ .statusCode(EidasConstants.SUCCESS_URI)
+ .inResponseTo("_".concat(Random.nextHexRandom16()))
+ .subjectNameIdFormat("afaf")
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_PREFIX + RandomStringUtils.randomAlphabetic(5))
+ .attributes(attributeMap.build())
+ .build();
+ }
+
+ private Map<String, Object> convertEidasAttrToSimpleMap(
+ ImmutableMap<AttributeDefinition<?>, ImmutableSet<? extends AttributeValue<?>>> attributeMap) {
+ final Map<String, Object> result = new HashMap<>();
+ for (final AttributeDefinition<?> el : attributeMap.keySet()) {
+ final Class<?> parameterizedType = el.getParameterizedType();
+ if (DateTime.class.equals(parameterizedType)) {
+ convertDateTime(attributeMap, result, el);
+ } else if (PostalAddress.class.equals(parameterizedType)) {
+ convertPostalAddress(attributeMap, result, el);
+ } else {
+ convertString(attributeMap, result, el);
+ }
+ }
+ return result;
+ }
+
+ private void convertString(ImmutableMap<AttributeDefinition<?>,
+ ImmutableSet<? extends AttributeValue<?>>> attributeMap,
+ Map<String, Object> result, AttributeDefinition<?> el) {
+ final List<String> natPersonIdObj = EidasResponseUtils
+ .translateStringListAttribute(el, attributeMap.get(el));
+ final String stringAttr = natPersonIdObj.get(0);
+ if (StringUtils.isNotEmpty(stringAttr)) {
+ result.put(el.getFriendlyName(), stringAttr);
+
+ }
+ }
+
+ private void convertPostalAddress(ImmutableMap<AttributeDefinition<?>,
+ ImmutableSet<? extends AttributeValue<?>>> attributeMap,
+ Map<String, Object> result, AttributeDefinition<?> el) {
+ final PostalAddress addressAttribute = EidasResponseUtils
+ .translateAddressAttribute(el, attributeMap.get(el).asList());
+ if (addressAttribute != null) {
+ result.put(el.getFriendlyName(), addressAttribute);
+
+ }
+ }
+
+ private void convertDateTime(ImmutableMap<AttributeDefinition<?>,
+ ImmutableSet<? extends AttributeValue<?>>> attributeMap,
+ Map<String, Object> result, AttributeDefinition<?> el) {
+ final DateTime attribute = EidasResponseUtils.translateDateAttribute(el, attributeMap.get(el).asList());
+ if (attribute != null) {
+ result.put(el.getFriendlyName(), attribute);
+
+ }
+ }
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java
index 36c0c2af..9060762c 100644
--- a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java
@@ -1,6 +1,7 @@
package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks;
import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -262,11 +263,10 @@ public class CreateIdentityLinkTaskEidNewTest {
Assert.assertNotNull("no piiTransactionId in pendingRequesdt",
storedPendingReq.getUniquePiiTransactionIdentifier());
- Assert.assertEquals("piiTransactionId", storedPendingReq.getUniquePiiTransactionIdentifier(),
- authBlockJson.get("piiTransactionId").asText());
- Assert.assertEquals("appId", randomTestSp, authBlockJson.get("appId").asText());
Assert.assertFalse("'challenge' is null", authBlockJson.get("challenge").asText().isEmpty());
- Assert.assertFalse("'timestamp' is null", authBlockJson.get("timestamp").asText().isEmpty());
+ Assert.assertFalse("'timestamp' is null", authBlockJson.get("issuedAt").asText().isEmpty());
+ assertNull("piiTransactionId", authBlockJson.get("piiTransactionId"));
+ assertNull("appId", authBlockJson.get("appId"));
Assert.assertFalse("binding pubKey", authBlockJson.has("bindingPublicKey"));
@@ -385,12 +385,12 @@ public class CreateIdentityLinkTaskEidNewTest {
Assert.assertNotNull("deserialized AuthBlock", authBlockJson);
Assert.assertNotNull("no piiTransactionId in pendingRequesdt",
- storedPendingReq.getUniquePiiTransactionIdentifier());
- Assert.assertEquals("piiTransactionId", storedPendingReq.getUniquePiiTransactionIdentifier(),
- authBlockJson.get("piiTransactionId").asText());
- Assert.assertEquals("appId", randomTestSp, authBlockJson.get("appId").asText());
+ storedPendingReq.getUniquePiiTransactionIdentifier());
Assert.assertFalse("'challenge' is null", authBlockJson.get("challenge").asText().isEmpty());
- Assert.assertFalse("'timestamp' is null", authBlockJson.get("timestamp").asText().isEmpty());
+ Assert.assertFalse("'timestamp' is null", authBlockJson.get("issuedAt").asText().isEmpty());
+ assertNull("piiTransactionId", authBlockJson.get("piiTransactionId"));
+ assertNull("appId", authBlockJson.get("appId"));
+
Assert.assertTrue("binding pubKey", authBlockJson.has("bindingPublicKey"));
Assert.assertEquals("binding PubKey", bindingPubKey, authBlockJson.get("bindingPublicKey").asText());
diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java
index 68ef4560..4304ddd5 100644
--- a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java
+++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java
@@ -97,6 +97,8 @@ public class MsEidasNodeConstants {
public static final String PROP_EIDAS_REQUEST_LOA_MINIMUM_LEVEL =
"auth.eIDAS.node_v2.loa.requested.minimum";
+ public static final String PROP_CONFIG_AUTHBLOCK_LEGACY_USE =
+ "auth.eIDAS.authblock.use.legacy.version";
public static final String PROP_CONFIG_AUTHBLOCK_KEYSTORE_TYPE =
"auth.eIDAS.authblock.keystore.type";
public static final String PROP_CONFIG_AUTHBLOCK_KEYSTORE_PATH =