summaryrefslogtreecommitdiff
path: root/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java')
-rw-r--r--eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java1443
1 files changed, 749 insertions, 694 deletions
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java
index 2108e041..491fdf4a 100644
--- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java
+++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/builder/AbstractAuthenticationDataBuilder.java
@@ -1,29 +1,22 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 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:
+ * Licensed under the EUPL, Version 1.2 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:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * 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.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * 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.egiz.eaaf.core.impl.idp.auth.builder;
import java.io.ByteArrayInputStream;
@@ -32,18 +25,6 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map.Entry;
-
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
-import org.springframework.util.Base64Utils;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
import at.gv.egiz.eaaf.core.api.IRequest;
import at.gv.egiz.eaaf.core.api.data.EAAFConstants;
import at.gv.egiz.eaaf.core.api.data.ExtendedPVPAttributeDefinitions;
@@ -51,674 +32,748 @@ import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions;
import at.gv.egiz.eaaf.core.api.idp.IAuthData;
import at.gv.egiz.eaaf.core.api.idp.IAuthenticationDataBuilder;
import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;
-import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.IspConfiguration;
import at.gv.egiz.eaaf.core.api.idp.auth.data.IAuthProcessDataContainer;
import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;
-import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException;
-import at.gv.egiz.eaaf.core.exceptions.EAAFBuilderException;
-import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException;
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
-import at.gv.egiz.eaaf.core.exceptions.EAAFParserException;
-import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException;
+import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafParserException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
import at.gv.egiz.eaaf.core.exceptions.XPathException;
import at.gv.egiz.eaaf.core.impl.data.Pair;
import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData;
import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser;
import at.gv.egiz.eaaf.core.impl.utils.XPathUtils;
-
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.lang.NonNull;
+import org.springframework.util.Assert;
+import org.springframework.util.Base64Utils;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
public abstract class AbstractAuthenticationDataBuilder implements IAuthenticationDataBuilder {
- private static final Logger log = LoggerFactory.getLogger(AbstractAuthenticationDataBuilder.class);
-
- /**
- * Identify authProcessData that should be directly mapped into authData
- */
- public static final String GENERIC_AUTHDATA_IDENTIFIER = "authData_";
-
- public static final String CONFIG_PROP_ENABLE_IDL_ATTRIBUTE_ESCAPEING = "configuration.bugfix.enable.idl.escaping";
-
- protected Collection<String> includedToGenericAuthData = null;
- @Autowired protected IConfigurationWithSP basicConfig;
-
- @Override
- public IAuthData buildAuthenticationData(IRequest pendingReq) throws EAAFAuthenticationException {
- IAuthData authData = null;
- final IAuthProcessDataContainer authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class);
-
- try {
- if (authProcessData.isEIDProcess()) {
- log.debug("Building AuthData from new E-ID information ... ");
- authData = getAuthDataInstance(pendingReq);
- Assert.notNull(authData, "AuthData is null");
-
- log.trace("Adding generic AuthData information ... ");
- buildInternalAuthDataGeneric(authData, authProcessData, pendingReq);
-
- log.trace("Build service-specific AuthData information ... ");
- buildServiceSpecificAuthenticationData(authData, pendingReq);
-
- } else {
- log.info("User authentication uses the deprecated. Building AuthData from deprecated information ... ");
- authData = buildDeprecatedAuthData(pendingReq);
- Assert.notNull(authData, "AuthData is null");
-
- }
-
- } catch ( final EAAFAuthenticationException e) {
- throw e;
-
- } catch (XPathException | DOMException | EAAFException e) {
- log.warn("Can not build authentication data from auth. process information");
- throw new EAAFAuthenticationException("builder.11", new Object[]{e.getMessage()}, e);
-
- }
-
- log.trace("AuthData generation finished");
- return authData;
-
- }
-
- /**
- * * @param pendingReq current pendingRequest
- *
- * @param pendingReq current pendingRequest
- * @return {@link IAuthData} but never <code>null</code>
- * @throws EAAFException
- */
- @NonNull
- abstract protected IAuthData getAuthDataInstance(IRequest pendingReq) throws EAAFException;
-
- /**
- * Build service-specific AuthData by using information from E-ID
- * This builder uses vSZ, MDS and Consent as input information
- *
- * @param pendingReq current pendingRequest
- * @return {@link IAuthData} but never <code>null</code>
- * @throws EAAFException
- */
- abstract protected void buildServiceSpecificAuthenticationData(IAuthData authData, IRequest pendingReq) throws EAAFException;
-
-
- /**
- * Add generic E-ID information into already existing AuthData
- *
- * @param authData
- * @param authProcessData
- * @param pendingReq
- */
- private void buildInternalAuthDataGeneric(@NonNull IAuthData authData,
- @NonNull IAuthProcessDataContainer authProcessData, @NonNull IRequest pendingReq) {
- Assert.notNull(pendingReq, "PendingRequest is null");
- Assert.notNull(authData, "AuthData is null");
- Assert.notNull(authProcessData, "AuthProcessData is null");
-
- if (!(authData instanceof AuthenticationData)) {
- log.error("AuthData has no suitable type! Requires: {}", AuthenticationData.class.getName());
- throw new RuntimeException("AuthData has no suitable type! Requires: " + AuthenticationData.class.getName());
-
- }
-
- final AuthenticationData internalAuthData = (AuthenticationData)authData;
-
- //TODO: check if it is needed
-// if (authProcessData.getGenericSessionDataStorage() != null &&
-// !authProcessData.getGenericSessionDataStorage().isEmpty())
-// includedToGenericAuthData = authProcessData.getGenericSessionDataStorage().keySet();
-// else
- includedToGenericAuthData = new ArrayList<String>();
-
- //####################################################
- //set general authData info's
- internalAuthData.setAuthenticationIssuer(pendingReq.getAuthURL());
- internalAuthData.setSsoSession(pendingReq.needSingleSignOnFunctionality());
- internalAuthData.setBaseIDTransferRestrication(pendingReq.getServiceProviderConfiguration().hasBaseIdTransferRestriction());
-
- //####################################################
- //set MDS and vSZ
- internalAuthData.setFamilyName(authProcessData.getGenericDataFromSession(ExtendedPVPAttributeDefinitions.PRINCIPAL_NAME_NAME, String.class));
- internalAuthData.setGivenName(authProcessData.getGenericDataFromSession(ExtendedPVPAttributeDefinitions.GIVEN_NAME_NAME, String.class));
- internalAuthData.setDateOfBirth(authProcessData.getGenericDataFromSession(ExtendedPVPAttributeDefinitions.BIRTHDATE_NAME, String.class));
- internalAuthData.setEncSourceId(authProcessData.getGenericDataFromSession(ExtendedPVPAttributeDefinitions.EID_ENCRYPTED_SOURCEID_NAME, String.class));
- internalAuthData.setEncSourceIdType(authProcessData.getGenericDataFromSession(ExtendedPVPAttributeDefinitions.EID_ENCRYPTED_SOURCEID_TYPE_NAME, String.class));
-
- //####################################################
- //set QAA level
- setQAALevel(internalAuthData, authProcessData, pendingReq);
-
-
- //####################################################
- //set isForeigner flag
- setFlagForeigner(internalAuthData, authProcessData, pendingReq);
-
-
- //####################################################
- //set citizen country-code
- setCitizenCountryCode(internalAuthData, authProcessData, pendingReq);
-
-
- //set generic authProcessData to authdata
- for (final Entry<String, Object> el : authProcessData.getGenericSessionDataStorage().entrySet()) {
- if (el.getKey().startsWith(GENERIC_AUTHDATA_IDENTIFIER)) {
- log.trace("Find generic authProcessData {}. Map it directly to authData", el.getKey());
- try {
- internalAuthData.setGenericData(el.getKey(), el.getValue());
-
- } catch (final EAAFStorageException e) {
- log.warn("Can NOT set authData with key: {}", el.getKey(), null, e);
-
- }
-
- }
-
- }
-
-
- }
-
- /**
- * Parse citzen country-code into AuthData
- *
- * @param internalAuthData
- * @param authProcessData
- * @param pendingReq
- */
- private void setCitizenCountryCode(AuthenticationData authData, IAuthProcessDataContainer authProcessData,
- IRequest pendingReq) {
- includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_ISSUING_NATION_NAME);
- final String pvpCCCAttr = authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class);
- if (StringUtils.isNotEmpty(pvpCCCAttr)) {
- authData.setCiticenCountryCode(pvpCCCAttr);
- log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_ISSUING_NATION_FRIENDLY_NAME);
-
- } else {
- if (authData.isForeigner()) {
- //TODO!!!!
-
- } else {
- authData.setCiticenCountryCode(basicConfig.getBasicConfiguration(
- IConfigurationWithSP.CONFIG_PROPS_AUTH_DEFAULT_COUNTRYCODE,
- EAAFConstants.COUNTRYCODE_AUSTRIA));
-
- }
- }
-
- }
-
- /**
- * parse QAA Level into AuthData
- *
- * @param authData
- * @param authProcessData
- * @param pendingReq
- */
- private void setQAALevel(@NonNull AuthenticationData authData,
- @NonNull IAuthProcessDataContainer authProcessData, @NonNull IRequest pendingReq) {
- includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME);
- String currentLoA = null;
- if (StringUtils.isNotEmpty(authProcessData.getQAALevel()))
- currentLoA = authProcessData.getQAALevel();
- else {
- currentLoA = authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, String.class);
- if (StringUtils.isNotEmpty(currentLoA)) {
- log.debug("Find PVP-Attr '" + PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME + "':" + currentLoA
- + " --> Parse QAA-Level from that attribute.");
-
- }
- }
- if (StringUtils.isNotEmpty(currentLoA)) {
- if (currentLoA.startsWith(EAAFConstants.EIDAS_LOA_PREFIX)) {
- authData.seteIDASLoA(currentLoA);
-
- } else
- log.info("Only eIDAS LoAs are supported by this implementation");
-
- } else {
- log.info("No QAA level found. Set to default level " + EAAFConstants.EIDAS_LOA_LOW);
- authData.seteIDASLoA(EAAFConstants.EIDAS_LOA_LOW);
-
- }
-
- }
-
- /**
- * Parse Foreigner information into AuthData
- *
- * @param authData
- * @param authProcessData
- * @param pendingReq
- */
- private void setFlagForeigner(AuthenticationData authData, IAuthProcessDataContainer authProcessData, IRequest pendingReq) {
- //TODO: change to new eIDAS-token attribute identifier
- if (authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_STORK_TOKEN_NAME) != null) {
- log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_STORK_TOKEN_FRIENDLY_NAME
- + " --> Set 'isForeigner' flag to TRUE");
- authData.setForeigner(true);
-
- } else {
- authData.setForeigner(authProcessData.isForeigner());
-
- }
- }
-
- /**
- * Build authentication data by using information from citizen-card or mobile-phone signature
- * This builder uses IdentityLink, AuthBlock, full MIS mandate as input information
- *
- * @param pendingReq current pendingRequest
- * @return {@link IAuthData} but never <code>null</code>
- * @throws EAAFException
- */
- @Deprecated
- @NonNull
- abstract protected IAuthData buildDeprecatedAuthData(IRequest pendingReq) throws EAAFException;
-
- @Deprecated
- protected void generateDeprecatedBasicAuthData(AuthenticationData authData, IRequest pendingReq,
- IAuthProcessDataContainer authProcessData) throws EAAFBuilderException, EAAFConfigurationException, XPathException, DOMException, EAAFParserException {
-
- if (authProcessData.getGenericSessionDataStorage() != null &&
- !authProcessData.getGenericSessionDataStorage().isEmpty())
- includedToGenericAuthData = authProcessData.getGenericSessionDataStorage().keySet();
- else
- includedToGenericAuthData = new ArrayList<String>();
-
- //####################################################
- //set general authData info's
- authData.setAuthenticationIssuer(pendingReq.getAuthURL());
- authData.setSsoSession(pendingReq.needSingleSignOnFunctionality());
- authData.setBaseIDTransferRestrication(pendingReq.getServiceProviderConfiguration().hasBaseIdTransferRestriction());
-
-
- //####################################################
- //parse user info's from identityLink
- IIdentityLink idlFromPVPAttr = null;
- final IIdentityLink identityLink = authProcessData.getIdentityLink();
- if (identityLink != null) {
- parseBasicUserInfosFromIDL(authData, identityLink, includedToGenericAuthData);
-
- } else {
- // identityLink is not direct in MOASession
- final String pvpAttrIDL = authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_IDENTITY_LINK_NAME, String.class);
- //find PVP-Attr. which contains the IdentityLink
- if (StringUtils.isNotEmpty(pvpAttrIDL)) {
- log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_IDENTITY_LINK_FRIENDLY_NAME
- + " --> Parse basic user info's from that attribute.");
- InputStream idlStream = null;
- try {
- idlStream = new ByteArrayInputStream(Base64Utils.decodeFromString(pvpAttrIDL));
- idlFromPVPAttr = new SimpleIdentityLinkAssertionParser(idlStream).parseIdentityLink();
- parseBasicUserInfosFromIDL(authData, idlFromPVPAttr, includedToGenericAuthData);
-
- //set identitylink into AuthProcessData
- authProcessData.setIdentityLink(idlFromPVPAttr);;
-
- } catch (final EAAFParserException e) {
- log.warn("Received IdentityLink is not valid", e);
-
- } catch (final Exception e) {
- log.warn("Received IdentityLink is not valid", e);
-
- } finally {
- try {
- includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_IDENTITY_LINK_NAME);
- if (idlStream != null)
- idlStream.close();
-
- } catch (final IOException e) {
- log.warn("Close InputStream FAILED.", e);
-
- }
- }
- }
-
- //if no basic user info's are set yet, parse info's single PVP-Attributes
- if (StringUtils.isEmpty(authData.getFamilyName())) {
- log.debug("No IdentityLink found or not parseable --> Parse basic user info's from single PVP-Attributes.");
- authData.setFamilyName(authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.PRINCIPAL_NAME_NAME, String.class));
- authData.setGivenName(authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.GIVEN_NAME_NAME, String.class));
- authData.setDateOfBirth(authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.BIRTHDATE_NAME, String.class));
- authData.setIdentificationValue(authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_SOURCE_PIN_NAME, String.class));
- authData.setIdentificationType(authProcessData.getGenericDataFromSession(PVPAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME, String.class));
-
- //remove corresponding keys from genericSessionData if exists
- includedToGenericAuthData.remove(PVPAttributeDefinitions.PRINCIPAL_NAME_NAME);
- includedToGenericAuthData.remove(PVPAttributeDefinitions.GIVEN_NAME_NAME);
- includedToGenericAuthData.remove(PVPAttributeDefinitions.BIRTHDATE_NAME);
- includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_NAME);
- includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME);
- }
-
- }
-
- if (authData.getIdentificationType() != null &&
- !authData.getIdentificationType().equals(EAAFConstants.URN_PREFIX_BASEID)) {
- log.trace("IdentificationType is not a baseID --> clear it. ");
- authData.setBPK(authData.getIdentificationValue());
- authData.setBPKType(authData.getIdentificationType());
-
- authData.setIdentificationValue(null);
- authData.setIdentificationType(null);
- }
-
-
- //####################################################
- //set QAA level
- setQAALevel(authData, authProcessData, pendingReq);
-
-
- //####################################################
- //set isForeigner flag
- setFlagForeigner(authData, authProcessData, pendingReq);
-
-
- //####################################################
- //set citizen country-code
- setCitizenCountryCode(authData, authProcessData, pendingReq);
-
-
- //####################################################
- // set bPK and IdentityLink
- final String pvpbPKValue = getbPKValueFromPVPAttribute(authProcessData);
- final String pvpbPKTypeAttr = getbPKTypeFromPVPAttribute(authProcessData);
- final Pair<String, String> pvpEncbPKAttr = getEncryptedbPKFromPVPAttribute(authProcessData, authData, pendingReq.getServiceProviderConfiguration());
-
- //check if a unique ID for this citizen exists
- if (StringUtils.isEmpty(authData.getIdentificationValue()) &&
- StringUtils.isEmpty(pvpbPKValue) && StringUtils.isEmpty(authData.getBPK()) &&
- pvpEncbPKAttr == null) {
- log.info("Can not build authData, because moaSession include no bPK, encrypted bPK or baseID");
- throw new EAAFBuilderException("builder.08", new Object[]{"No " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME
- + " or " + PVPAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME
- + " or " + PVPAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME},
- "No " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME
- + " or " + PVPAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME
- + " or " + PVPAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME);
-
- }
-
- //check if bPK already added to AuthData matches OA
- if (StringUtils.isNotEmpty(authData.getBPK())
- && matchsReceivedbPKToOnlineApplication(pendingReq.getServiceProviderConfiguration(), authData.getBPKType()) ) {
- log.debug("Correct bPK is already included in AuthData.");
-
- //check if bPK received by PVP-Attribute matches OA
- } else if (StringUtils.isNotEmpty(pvpbPKValue) &&
- matchsReceivedbPKToOnlineApplication(pendingReq.getServiceProviderConfiguration(), pvpbPKTypeAttr)) {
- log.debug("Receive correct bPK from PVP-Attribute");
- authData.setBPK(pvpbPKValue);
- authData.setBPKType(pvpbPKTypeAttr);
-
- // baseID is in AuthSesson --> calculate bPK directly
- } else if (StringUtils.isNotEmpty(authData.getIdentificationValue())) {
- log.debug("Citizen baseID is in MOASession --> calculate bPK from this.");
- final Pair<String, String> result = buildOAspecificbPK(pendingReq, authData);
- authData.setBPK(result.getFirst());
- authData.setBPKType(result.getSecond());
-
- //check if decrypted bPK exists
- } else if (pvpEncbPKAttr != null) {
- log.debug("Receive bPK as encrypted bPK and decryption was possible.");
- authData.setBPK(pvpEncbPKAttr.getFirst());
- authData.setBPKType(pvpEncbPKAttr.getSecond());
-
- //ask SZR to get bPK
- } else {
- String notValidbPK = authData.getBPK();
- String notValidbPKType = authData.getBPKType();
- if (StringUtils.isEmpty(notValidbPK) &&
- StringUtils.isEmpty(notValidbPKType)) {
- notValidbPK = pvpbPKValue;
- notValidbPKType = pvpbPKTypeAttr;
-
- if (StringUtils.isEmpty(notValidbPK) &&
- StringUtils.isEmpty(notValidbPKType)) {
- log.error("No bPK in MOASession. THIS error should not occur any more.");
- throw new NullPointerException("No bPK in MOASession. THIS error should not occur any more.");
- }
- }
-
- final Pair<String, String> baseIDFromSZR = getbaseIDFromSZR(authData, notValidbPK, notValidbPKType);
- if (baseIDFromSZR != null) {
- log.info("Receive citizen baseID from SRZ. Authentication can be completed");
- authData.setIdentificationValue(baseIDFromSZR.getFirst());
- authData.setIdentificationType(baseIDFromSZR.getSecond());
- final Pair<String, String> result = buildOAspecificbPK(pendingReq, authData);
- authData.setBPK(result.getFirst());
- authData.setBPKType(result.getSecond());
-
- } else {
- log.warn("Can not build authData, because moaSession include no valid bPK, encrypted bPK or sourceID");
- throw new EAAFBuilderException("builder.13", new Object[]{pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()},
- "No valid " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME
- + " or " + PVPAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME
- + " or " + PVPAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME);
-
- }
- }
-
- //build IdentityLink
- if (authProcessData.getIdentityLink() != null)
- authData.setIdentityLink(buildOAspecificIdentityLink(
- pendingReq.getServiceProviderConfiguration(),
- authProcessData.getIdentityLink(),
- authData.getBPK(),
- authData.getBPKType()));
- else
- log.info("Can NOT set IdentityLink. Msg: No IdentityLink found");
-
- }
-
- //extract a encrypted bPK from PVP attrobute
- @Deprecated
- protected abstract Pair<String, String> getEncryptedbPKFromPVPAttribute(IAuthProcessDataContainer authProcessDataContainer,
- AuthenticationData authData, ISPConfiguration spConfig) throws EAAFBuilderException;
-
- //request baseId from SRZ
- @Deprecated
- protected abstract Pair<String, String> getbaseIDFromSZR(AuthenticationData authData, String notValidbPK,
- String notValidbPKType);
-
- @Deprecated
- protected Pair<String, String> buildOAspecificbPK(IRequest pendingReq, AuthenticationData authData) throws EAAFBuilderException {
- final ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration();
-
- final String baseID = authData.getIdentificationValue();
- final String baseIDType = authData.getIdentificationType();
- Pair<String, String> sectorSpecId = null;
-
- if (EAAFConstants.URN_PREFIX_BASEID.equals(baseIDType)) {
- //SAML1 legacy target parameter work-around
- final String spTargetId = oaParam.getAreaSpecificTargetIdentifier();
- log.debug("Use OA target identifier '" + spTargetId + "' from configuration");
-
- //calculate sector specific unique identifier
- sectorSpecId = new BPKBuilder().generateAreaSpecificPersonIdentifier(baseID, spTargetId);
-
- } else {
- log.error("!!!baseID-element does not include a baseID. This should not be happen any more!!!");
- sectorSpecId = Pair.newInstance(baseID, baseIDType);
-
- }
-
- log.trace("Authenticate user with bPK:" + sectorSpecId.getFirst() + " Type:" + sectorSpecId.getSecond());
- return sectorSpecId;
-
- }
-
- @Deprecated
- protected IIdentityLink buildOAspecificIdentityLink(ISPConfiguration spConfig, IIdentityLink idl, String bPK, String bPKType) throws EAAFConfigurationException, XPathException, DOMException, EAAFParserException {
- if (spConfig.hasBaseIdTransferRestriction()) {
- log.debug("SP: " + spConfig.getUniqueIdentifier() + " has baseId transfer restriction. Remove baseId from IDL ...");
- final Element idlassertion = idl.getSamlAssertion();
- //set bpk/wpbk;
- final Node prIdentification = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH);
- prIdentification.getFirstChild().setNodeValue(bPK);
- //set bkp/wpbk type
- final Node prIdentificationType = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_TYPE_XPATH);
- prIdentificationType.getFirstChild().setNodeValue(bPKType);
-
- final SimpleIdentityLinkAssertionParser idlparser = new SimpleIdentityLinkAssertionParser(idlassertion);
- return idlparser.parseIdentityLink();
-
- } else
- return idl;
-
- }
-
- /**
- * Check a bPK-Type against a Service-Provider configuration <br>
- * If bPK-Type is <code>null</code> the result is <code>false</code>.
- *
- * @param oaParam Service-Provider configuration, never null
- * @param bPKType bPK-Type to check
- * @return true, if bPK-Type matchs to Service-Provider configuration, otherwise false
- */
- @Deprecated
- protected boolean matchsReceivedbPKToOnlineApplication(ISPConfiguration oaParam, String bPKType) {
- return oaParam.getAreaSpecificTargetIdentifier().equals(bPKType);
-
- }
-
- /**
- * Parse information from an IdentityLink into AuthData object
- *
- * @param authData
- * @param identityLink
- * @param includedGenericSessionData
- */
- @Deprecated
- private void parseBasicUserInfosFromIDL(AuthenticationData authData, IIdentityLink identityLink, Collection<String> includedGenericSessionData) {
- authData.setIdentificationValue(identityLink.getIdentificationValue());
- authData.setIdentificationType(identityLink.getIdentificationType());
-
- /* GivenNames and FamilyNames with simple Apostrophe were escaped with &#39;
- * in IdentityLinkParser since 5 years. This feature was bug-fix for an SL1.0 AuthBlock problem.
- * However, the authentication attributes (SAML2, eIDAS, OpenID-Connect) also includes this escaped values,
- * but there it is not neccesary. We fix this problem in 3.4.3, but the fix can be deactivated
- * for dependency reasons.
- */
- if (basicConfig.getBasicConfigurationBoolean(CONFIG_PROP_ENABLE_IDL_ATTRIBUTE_ESCAPEING, false)) {
- authData.setGivenName(identityLink.getGivenName().replaceAll("'", "&#39;"));
- authData.setFamilyName(identityLink.getFamilyName().replaceAll("'", "&#39;"));
-
- } else {
- authData.setGivenName(identityLink.getGivenName());
- authData.setFamilyName(identityLink.getFamilyName());
-
- }
-
- authData.setDateOfBirth(identityLink.getDateOfBirth());
-
-
- //remove corresponding keys from genericSessionData if exists
- includedGenericSessionData.remove(PVPAttributeDefinitions.PRINCIPAL_NAME_NAME);
- includedGenericSessionData.remove(PVPAttributeDefinitions.GIVEN_NAME_NAME);
- includedGenericSessionData.remove(PVPAttributeDefinitions.BIRTHDATE_NAME);
- includedGenericSessionData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_NAME);
- includedGenericSessionData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME);
-
- }
-
- /**
- * Get bPK from PVP Attribute 'BPK_NAME', which could be exist in
- * MOASession as 'GenericData' <br> <pre><code>session.getGenericDataFromSession(PVPConstants.BPK_NAME, String.class)</code></pre>
- *
- * @param session MOASession, but never null
- * @return bPK, which was received by PVP-Attribute, or <code>null</code> if no attribute exists
- */
- @Deprecated
- private String getbPKValueFromPVPAttribute(IAuthProcessDataContainer session) {
- String pvpbPKValueAttr = session.getGenericDataFromSession(PVPAttributeDefinitions.BPK_NAME, String.class);
- if (StringUtils.isNotEmpty(pvpbPKValueAttr)) {
-
- //fix a wrong bPK-value prefix, which was used in some PVP Standardportal implementations
- if (pvpbPKValueAttr.startsWith("bPK:")) {
- log.warn("Attribute " + PVPAttributeDefinitions.BPK_NAME
- + " contains a not standardize prefix! Staring attribute value correction process ...");
- pvpbPKValueAttr = pvpbPKValueAttr.substring("bPK:".length());
-
- }
-
- final String[] spitted = pvpbPKValueAttr.split(":");
- if (spitted.length == 2) {
- log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME);
- return spitted[1];
-
-
-
- } else if (spitted.length > 2) {
- log.warn("Attribute " + PVPAttributeDefinitions.BPK_NAME + " has a wrong encoding and can NOT be USED!"
- + " Value:" + pvpbPKValueAttr);
- return null;
-
- } else {
- log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME + " without prefix. Use it as it is");
- return spitted[0];
-
- }
-
- }
-
- return null;
- }
-
- /**
- * Get bPK-Type from PVP Attribute 'EID_SECTOR_FOR_IDENTIFIER_NAME', which could be exist in
- * MOASession as 'GenericData' <br> <pre><code>session.getGenericDataFromSession(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME, String.class)</code></pre>
- *
- * @param session MOASession, but never null
- * @return bPKType, which was received by PVP-Attribute, or <code>null</code> if no attribute exists
- */
- @Deprecated
- private String getbPKTypeFromPVPAttribute(IAuthProcessDataContainer session) {
- final String pvpbPKTypeAttr = session.getGenericDataFromSession(PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, String.class);
-
- if (StringUtils.isNotEmpty(pvpbPKTypeAttr)) {
-// //fix a wrong bPK-Type encoding, which was used in some PVP Standardportal implementations
-// if (pvpbPKTypeAttr.startsWith(EAAFConstants.URN_PREFIX_CDID) &&
-// !pvpbPKTypeAttr.substring(EAAFConstants.URN_PREFIX_CDID.length(),
-// EAAFConstants.URN_PREFIX_CDID.length() + 1).equals("+")) {
-// log.warn("Receive uncorrect encoded bBKType attribute " + pvpbPKTypeAttr + " Starting attribute value correction ... ");
-// pvpbPKTypeAttr = EAAFConstants.URN_PREFIX_CDID + "+" + pvpbPKTypeAttr.substring(EAAFConstants.URN_PREFIX_CDID.length() + 1);
-//
-// }
- log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME);
- return pvpbPKTypeAttr;
- }
-
- return null;
-
-
- /*
- * INFO: This code could be used to extract the bPKType from 'PVPConstants.BPK_NAME',
- * because the prefix of BPK_NAME attribute contains the postfix of the bPKType
- *
- * Now, all PVP Standardportals should be able to send 'EID_SECTOR_FOR_IDENTIFIER'
- * PVP attributes
- */
-// String pvpbPKValueAttr = session.getGenericDataFromSession(PVPConstants.BPK_NAME, String.class);
-// String[] spitted = pvpbPKValueAttr.split(":");
-// if (MiscUtil.isEmpty(authData.getBPKType())) {
-// Logger.debug("PVP assertion contains NO bPK/wbPK target attribute. " +
-// "Starting target extraction from bPK/wbPK prefix ...");
-// //exract bPK/wbPK type from bpk attribute value prefix if type is
-// //not transmitted as single attribute
-// Pattern pattern = Pattern.compile("[a-zA-Z]{2}(-[a-zA-Z]+)?");
-// Matcher matcher = pattern.matcher(spitted[0]);
-// if (matcher.matches()) {
-// //find public service bPK
-// authData.setBPKType(Constants.URN_PREFIX_CDID + "+" + spitted[0]);
-// Logger.debug("Found bPK prefix. Set target to " + authData.getBPKType());
-//
-// } else {
-// //find business service wbPK
-// authData.setBPKType(Constants.URN_PREFIX_WBPK+ "+" + spitted[0]);
-// Logger.debug("Found wbPK prefix. Set target to " + authData.getBPKType());
-//
-// }
-// }
-
- }
+ private static final Logger log =
+ LoggerFactory.getLogger(AbstractAuthenticationDataBuilder.class);
+
+ /**
+ * Identify authProcessData that should be directly mapped into authData.
+ */
+ public static final String GENERIC_AUTHDATA_IDENTIFIER = "authData_";
+
+ public static final String CONFIG_PROP_ENABLE_IDL_ATTRIBUTE_ESCAPEING =
+ "configuration.bugfix.enable.idl.escaping";
+
+ protected Collection<String> includedToGenericAuthData = null;
+ @Autowired
+ protected IConfigurationWithSP basicConfig;
+
+ @Override
+ public IAuthData buildAuthenticationData(final IRequest pendingReq)
+ throws EaafAuthenticationException {
+ IAuthData authData = null;
+ final IAuthProcessDataContainer authProcessData =
+ pendingReq.getSessionData(AuthProcessDataWrapper.class);
+
+ try {
+ if (authProcessData.isEIDProcess()) {
+ log.debug("Building AuthData from new E-ID information ... ");
+ authData = getAuthDataInstance(pendingReq);
+ Assert.notNull(authData, "AuthData is null");
+
+ log.trace("Adding generic AuthData information ... ");
+ buildInternalAuthDataGeneric(authData, authProcessData, pendingReq);
+
+ log.trace("Build service-specific AuthData information ... ");
+ buildServiceSpecificAuthenticationData(authData, pendingReq);
+
+ } else {
+ log.info(
+ "User authentication uses the deprecated. Building AuthData from deprecated information ... ");
+ authData = buildDeprecatedAuthData(pendingReq);
+ Assert.notNull(authData, "AuthData is null");
+
+ }
+
+ } catch (final EaafAuthenticationException e) {
+ throw e;
+
+ } catch (XPathException | DOMException | EaafException e) {
+ log.warn("Can not build authentication data from auth. process information");
+ throw new EaafAuthenticationException("builder.11", new Object[] {e.getMessage()}, e);
+
+ }
+
+ log.trace("AuthData generation finished");
+ return authData;
+
+ }
+
+ /**
+ * * @param pendingReq current pendingRequest.
+ *
+ * @param pendingReq current pendingRequest
+ * @return {@link IAuthData} but never <code>null</code>
+ * @throws EaafException In case of an error
+ */
+ @NonNull
+ protected abstract IAuthData getAuthDataInstance(IRequest pendingReq) throws EaafException;
+
+ /**
+ * Build service-specific AuthData by using information from E-ID This builder uses vSZ, MDS and
+ * Consent as input information.
+ *
+ * @param pendingReq current pendingRequest
+ * @return {@link IAuthData} but never <code>null</code>
+ * @throws EaafException In case of an error
+ */
+ protected abstract void buildServiceSpecificAuthenticationData(IAuthData authData,
+ IRequest pendingReq) throws EaafException;
+
+
+ /**
+ * Add generic E-ID information into already existing AuthData.
+ *
+ * @param authData AuthData object
+ * @param authProcessData Authentication information holder from current pending request
+ * @param pendingReq current pending request
+ */
+ private void buildInternalAuthDataGeneric(@NonNull final IAuthData authData,
+ @NonNull final IAuthProcessDataContainer authProcessData,
+ @NonNull final IRequest pendingReq) {
+ Assert.notNull(pendingReq, "PendingRequest is null");
+ Assert.notNull(authData, "AuthData is null");
+ Assert.notNull(authProcessData, "AuthProcessData is null");
+
+ if (!(authData instanceof AuthenticationData)) {
+ log.error("AuthData has no suitable type! Requires: {}", AuthenticationData.class.getName());
+ throw new RuntimeException(
+ "AuthData has no suitable type! Requires: " + AuthenticationData.class.getName());
+
+ }
+
+ final AuthenticationData internalAuthData = (AuthenticationData) authData;
+
+ // TODO: check if it is needed
+ // if (authProcessData.getGenericSessionDataStorage() != null &&
+ // !authProcessData.getGenericSessionDataStorage().isEmpty())
+ // includedToGenericAuthData = authProcessData.getGenericSessionDataStorage().keySet();
+ // else
+ includedToGenericAuthData = new ArrayList<>();
+
+ // ####################################################
+ // set general authData info's
+ internalAuthData.setAuthenticationIssuer(pendingReq.getAuthUrl());
+ internalAuthData.setSsoSession(pendingReq.needSingleSignOnFunctionality());
+ internalAuthData.setBaseIdTransferRestrication(
+ pendingReq.getServiceProviderConfiguration().hasBaseIdTransferRestriction());
+
+ // ####################################################
+ // set MDS and vSZ
+ internalAuthData.setFamilyName(authProcessData
+ .getGenericDataFromSession(PVPAttributeDefinitions.PRINCIPAL_NAME_NAME, String.class));
+ internalAuthData.setGivenName(authProcessData
+ .getGenericDataFromSession(PVPAttributeDefinitions.GIVEN_NAME_NAME, String.class));
+ internalAuthData.setDateOfBirth(authProcessData
+ .getGenericDataFromSession(PVPAttributeDefinitions.BIRTHDATE_NAME, String.class));
+ internalAuthData.setEncSourceId(authProcessData.getGenericDataFromSession(
+ ExtendedPVPAttributeDefinitions.EID_ENCRYPTED_SOURCEID_NAME, String.class));
+ internalAuthData.setEncSourceIdType(authProcessData.getGenericDataFromSession(
+ ExtendedPVPAttributeDefinitions.EID_ENCRYPTED_SOURCEID_TYPE_NAME, String.class));
+
+ // ####################################################
+ // set QAA level
+ setQaaLevel(internalAuthData, authProcessData, pendingReq);
+
+
+ // ####################################################
+ // set isForeigner flag
+ setFlagForeigner(internalAuthData, authProcessData, pendingReq);
+
+
+ // ####################################################
+ // set citizen country-code
+ setCitizenCountryCode(internalAuthData, authProcessData, pendingReq);
+
+
+ // set generic authProcessData to authdata
+ for (final Entry<String, Object> el : authProcessData.getGenericSessionDataStorage()
+ .entrySet()) {
+ if (el.getKey().startsWith(GENERIC_AUTHDATA_IDENTIFIER)) {
+ log.trace("Find generic authProcessData {}. Map it directly to authData", el.getKey());
+ try {
+ internalAuthData.setGenericData(el.getKey(), el.getValue());
+
+ } catch (final EaafStorageException e) {
+ log.warn("Can NOT set authData with key: {}", el.getKey(), null, e);
+
+ }
+
+ }
+
+ }
+
+
+ }
+
+ /**
+ * Parse citzen country-code into AuthData.
+ *
+ * @param authData Current authentication data
+ * @param authProcessData Authentication information holder from current pending request
+ * @param pendingReq Current pending request
+ */
+ private void setCitizenCountryCode(final AuthenticationData authData,
+ final IAuthProcessDataContainer authProcessData, final IRequest pendingReq) {
+ includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_ISSUING_NATION_NAME);
+ final String pvpCccAttr = authProcessData
+ .getGenericDataFromSession(PVPAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class);
+ if (StringUtils.isNotEmpty(pvpCccAttr)) {
+ authData.setCiticenCountryCode(pvpCccAttr);
+ log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_ISSUING_NATION_FRIENDLY_NAME);
+
+ } else {
+ if (authData.isForeigner()) {
+ // TODO!!!!
+
+ } else {
+ authData.setCiticenCountryCode(basicConfig.getBasicConfiguration(
+ IConfigurationWithSP.CONFIG_PROPS_AUTH_DEFAULT_COUNTRYCODE,
+ EAAFConstants.COUNTRYCODE_AUSTRIA));
+
+ }
+ }
+
+ }
+
+ /**
+ * parse QAA Level into AuthData.
+ *
+ * @param authData current authentication data
+ * @param authProcessData Authentication information holder from current pending request
+ * @param pendingReq current pending request
+ */
+ private void setQaaLevel(@NonNull final AuthenticationData authData,
+ @NonNull final IAuthProcessDataContainer authProcessData,
+ @NonNull final IRequest pendingReq) {
+ includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME);
+ String currentLoA = null;
+ if (StringUtils.isNotEmpty(authProcessData.getQAALevel())) {
+ currentLoA = authProcessData.getQAALevel();
+ } else {
+ currentLoA = authProcessData.getGenericDataFromSession(
+ PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, String.class);
+ if (StringUtils.isNotEmpty(currentLoA)) {
+ log.debug(
+ "Find PVP-Attr '" + PVPAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME
+ + "':" + currentLoA + " --> Parse QAA-Level from that attribute.");
+
+ }
+ }
+ if (StringUtils.isNotEmpty(currentLoA)) {
+ if (currentLoA.startsWith(EAAFConstants.EIDAS_LOA_PREFIX)) {
+ authData.setEidasLoa(currentLoA);
+
+ } else {
+ log.info("Only eIDAS LoAs are supported by this implementation");
+ }
+
+ } else {
+ log.info("No QAA level found. Set to default level " + EAAFConstants.EIDAS_LOA_LOW);
+ authData.setEidasLoa(EAAFConstants.EIDAS_LOA_LOW);
+
+ }
+
+ }
+
+
+ private void setFlagForeigner(final AuthenticationData authData,
+ final IAuthProcessDataContainer authProcessData, final IRequest pendingReq) {
+ // TODO: change to new eIDAS-token attribute identifier
+ if (authProcessData
+ .getGenericDataFromSession(PVPAttributeDefinitions.EID_STORK_TOKEN_NAME) != null) {
+ log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_STORK_TOKEN_FRIENDLY_NAME
+ + " --> Set 'isForeigner' flag to TRUE");
+ authData.setForeigner(true);
+
+ } else {
+ authData.setForeigner(authProcessData.isForeigner());
+
+ }
+ }
+
+ /**
+ * Build authentication data by using information from citizen-card or mobile-phone signature This
+ * builder uses IdentityLink, AuthBlock, full MIS mandate as input information.
+ *
+ * @param pendingReq current pendingRequest
+ * @return {@link IAuthData} but never <code>null</code>
+ * @throws EaafException In case of an error
+ */
+ @Deprecated
+ @NonNull
+ protected abstract IAuthData buildDeprecatedAuthData(IRequest pendingReq) throws EaafException;
+
+ @Deprecated
+ protected void generateDeprecatedBasicAuthData(final AuthenticationData authData,
+ final IRequest pendingReq, final IAuthProcessDataContainer authProcessData)
+ throws EaafBuilderException, EaafConfigurationException, XPathException, DOMException,
+ EaafParserException {
+
+ if (authProcessData.getGenericSessionDataStorage() != null
+ && !authProcessData.getGenericSessionDataStorage().isEmpty()) {
+ includedToGenericAuthData = authProcessData.getGenericSessionDataStorage().keySet();
+ } else {
+ includedToGenericAuthData = new ArrayList<>();
+ }
+
+ // ####################################################
+ // set general authData info's
+ authData.setAuthenticationIssuer(pendingReq.getAuthUrl());
+ authData.setSsoSession(pendingReq.needSingleSignOnFunctionality());
+ authData.setBaseIdTransferRestrication(
+ pendingReq.getServiceProviderConfiguration().hasBaseIdTransferRestriction());
+
+
+ // ####################################################
+ // parse user info's from identityLink
+ IIdentityLink idlFromPvpAttr = null;
+ final IIdentityLink identityLink = authProcessData.getIdentityLink();
+ if (identityLink != null) {
+ parseBasicUserInfosFromIdl(authData, identityLink, includedToGenericAuthData);
+
+ } else {
+ // identityLink is not direct in MOASession
+ final String pvpAttrIdl = authProcessData
+ .getGenericDataFromSession(PVPAttributeDefinitions.EID_IDENTITY_LINK_NAME, String.class);
+ // find PVP-Attr. which contains the IdentityLink
+ if (StringUtils.isNotEmpty(pvpAttrIdl)) {
+ log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.EID_IDENTITY_LINK_FRIENDLY_NAME
+ + " --> Parse basic user info's from that attribute.");
+ InputStream idlStream = null;
+ try {
+ idlStream = new ByteArrayInputStream(Base64Utils.decodeFromString(pvpAttrIdl));
+ idlFromPvpAttr = new SimpleIdentityLinkAssertionParser(idlStream).parseIdentityLink();
+ parseBasicUserInfosFromIdl(authData, idlFromPvpAttr, includedToGenericAuthData);
+
+ // set identitylink into AuthProcessData
+ authProcessData.setIdentityLink(idlFromPvpAttr);
+
+ } catch (final EaafParserException e) {
+ log.warn("Received IdentityLink is not valid", e);
+
+ } catch (final Exception e) {
+ log.warn("Received IdentityLink is not valid", e);
+
+ } finally {
+ try {
+ includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_IDENTITY_LINK_NAME);
+ if (idlStream != null) {
+ idlStream.close();
+ }
+
+ } catch (final IOException e) {
+ log.warn("Close InputStream FAILED.", e);
+
+ }
+ }
+ }
+
+ // if no basic user info's are set yet, parse info's single PVP-Attributes
+ if (StringUtils.isEmpty(authData.getFamilyName())) {
+ log.debug(
+ "No IdentityLink found or not parseable --> Parse basic user info's from single PVP-Attributes.");
+ authData.setFamilyName(authProcessData
+ .getGenericDataFromSession(PVPAttributeDefinitions.PRINCIPAL_NAME_NAME, String.class));
+ authData.setGivenName(authProcessData
+ .getGenericDataFromSession(PVPAttributeDefinitions.GIVEN_NAME_NAME, String.class));
+ authData.setDateOfBirth(authProcessData
+ .getGenericDataFromSession(PVPAttributeDefinitions.BIRTHDATE_NAME, String.class));
+ authData.setIdentificationValue(authProcessData
+ .getGenericDataFromSession(PVPAttributeDefinitions.EID_SOURCE_PIN_NAME, String.class));
+ authData.setIdentificationType(authProcessData.getGenericDataFromSession(
+ PVPAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME, String.class));
+
+ // remove corresponding keys from genericSessionData if exists
+ includedToGenericAuthData.remove(PVPAttributeDefinitions.PRINCIPAL_NAME_NAME);
+ includedToGenericAuthData.remove(PVPAttributeDefinitions.GIVEN_NAME_NAME);
+ includedToGenericAuthData.remove(PVPAttributeDefinitions.BIRTHDATE_NAME);
+ includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_NAME);
+ includedToGenericAuthData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME);
+ }
+
+ }
+
+ if (authData.getIdentificationType() != null
+ && !authData.getIdentificationType().equals(EAAFConstants.URN_PREFIX_BASEID)) {
+ log.trace("IdentificationType is not a baseID --> clear it. ");
+ authData.setBpk(authData.getIdentificationValue());
+ authData.setBpkType(authData.getIdentificationType());
+
+ authData.setIdentificationValue(null);
+ authData.setIdentificationType(null);
+ }
+
+
+ // ####################################################
+ // set QAA level
+ setQaaLevel(authData, authProcessData, pendingReq);
+
+
+ // ####################################################
+ // set isForeigner flag
+ setFlagForeigner(authData, authProcessData, pendingReq);
+
+
+ // ####################################################
+ // set citizen country-code
+ setCitizenCountryCode(authData, authProcessData, pendingReq);
+
+
+ // ####################################################
+ // set bPK and IdentityLink
+ final String pvpBpkValue = getBpkValueFromPvpAttribute(authProcessData);
+ final String pvpBpkTypeAttr = getBpkTypeFromPvpAttribute(authProcessData);
+ final Pair<String, String> pvpEncBpkAttr = getEncryptedBpkFromPvpAttribute(authProcessData,
+ authData, pendingReq.getServiceProviderConfiguration());
+
+ // check if a unique ID for this citizen exists
+ if (StringUtils.isEmpty(authData.getIdentificationValue()) && StringUtils.isEmpty(pvpBpkValue)
+ && StringUtils.isEmpty(authData.getBpk()) && pvpEncBpkAttr == null) {
+ log.info(
+ "Can not build authData, because moaSession include no bPK, encrypted bPK or baseID");
+ throw new EaafBuilderException("builder.08",
+ new Object[] {"No " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME + " or "
+ + PVPAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME + " or "
+ + PVPAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME},
+ "No " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME + " or "
+ + PVPAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME + " or "
+ + PVPAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME);
+
+ }
+
+ // check if bPK already added to AuthData matches OA
+ if (StringUtils.isNotEmpty(authData.getBpk()) && matchsReceivedBpkToOnlineApplication(
+ pendingReq.getServiceProviderConfiguration(), authData.getBpkType())) {
+ log.debug("Correct bPK is already included in AuthData.");
+
+ // check if bPK received by PVP-Attribute matches OA
+ } else if (StringUtils.isNotEmpty(pvpBpkValue) && matchsReceivedBpkToOnlineApplication(
+ pendingReq.getServiceProviderConfiguration(), pvpBpkTypeAttr)) {
+ log.debug("Receive correct bPK from PVP-Attribute");
+ authData.setBpk(pvpBpkValue);
+ authData.setBpkType(pvpBpkTypeAttr);
+
+ // baseID is in AuthSesson --> calculate bPK directly
+ } else if (StringUtils.isNotEmpty(authData.getIdentificationValue())) {
+ log.debug("Citizen baseID is in MOASession --> calculate bPK from this.");
+ final Pair<String, String> result = buildOAspecificbPK(pendingReq, authData);
+ authData.setBpk(result.getFirst());
+ authData.setBpkType(result.getSecond());
+
+ // check if decrypted bPK exists
+ } else if (pvpEncBpkAttr != null) {
+ log.debug("Receive bPK as encrypted bPK and decryption was possible.");
+ authData.setBpk(pvpEncBpkAttr.getFirst());
+ authData.setBpkType(pvpEncBpkAttr.getSecond());
+
+ // ask SZR to get bPK
+ } else {
+ String notValidbPK = authData.getBpk();
+ String notValidBpkType = authData.getBpkType();
+ if (StringUtils.isEmpty(notValidbPK) && StringUtils.isEmpty(notValidBpkType)) {
+ notValidbPK = pvpBpkValue;
+ notValidBpkType = pvpBpkTypeAttr;
+
+ if (StringUtils.isEmpty(notValidbPK) && StringUtils.isEmpty(notValidBpkType)) {
+ log.error("No bPK in MOASession. THIS error should not occur any more.");
+ throw new NullPointerException(
+ "No bPK in MOASession. THIS error should not occur any more.");
+ }
+ }
+
+ final Pair<String, String> baseIdFromSzr =
+ getbaseIdFromSzr(authData, notValidbPK, notValidBpkType);
+ if (baseIdFromSzr != null) {
+ log.info("Receive citizen baseID from SRZ. Authentication can be completed");
+ authData.setIdentificationValue(baseIdFromSzr.getFirst());
+ authData.setIdentificationType(baseIdFromSzr.getSecond());
+ final Pair<String, String> result = buildOAspecificbPK(pendingReq, authData);
+ authData.setBpk(result.getFirst());
+ authData.setBpkType(result.getSecond());
+
+ } else {
+ log.warn(
+ "Can not build authData, because moaSession include no valid bPK, encrypted bPK or sourceID");
+ throw new EaafBuilderException("builder.13",
+ new Object[] {
+ pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()},
+ "No valid " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME + " or "
+ + PVPAttributeDefinitions.EID_SOURCE_PIN_FRIENDLY_NAME + " or "
+ + PVPAttributeDefinitions.ENC_BPK_LIST_FRIENDLY_NAME);
+
+ }
+ }
+
+ // build IdentityLink
+ if (authProcessData.getIdentityLink() != null) {
+ authData
+ .setIdentityLink(buildOAspecificIdentityLink(pendingReq.getServiceProviderConfiguration(),
+ authProcessData.getIdentityLink(), authData.getBpk(), authData.getBpkType()));
+ } else {
+ log.info("Can NOT set IdentityLink. Msg: No IdentityLink found");
+ }
+
+ }
+
+ // extract a encrypted bPK from PVP attrobute
+ @Deprecated
+ protected abstract Pair<String, String> getEncryptedBpkFromPvpAttribute(
+ IAuthProcessDataContainer authProcessDataContainer, AuthenticationData authData,
+ IspConfiguration spConfig) throws EaafBuilderException;
+
+ // request baseId from SRZ
+ @Deprecated
+ protected abstract Pair<String, String> getbaseIdFromSzr(AuthenticationData authData,
+ String notValidBpk, String notValidBpkType);
+
+ @Deprecated
+ protected Pair<String, String> buildOAspecificbPK(final IRequest pendingReq,
+ final AuthenticationData authData) throws EaafBuilderException {
+ final IspConfiguration oaParam = pendingReq.getServiceProviderConfiguration();
+
+ final String baseID = authData.getIdentificationValue();
+ final String baseIdType = authData.getIdentificationType();
+ Pair<String, String> sectorSpecId = null;
+
+ if (EAAFConstants.URN_PREFIX_BASEID.equals(baseIdType)) {
+ // SAML1 legacy target parameter work-around
+ final String spTargetId = oaParam.getAreaSpecificTargetIdentifier();
+ log.debug("Use OA target identifier '" + spTargetId + "' from configuration");
+
+ new BpkBuilder();
+ // calculate sector specific unique identifier
+ sectorSpecId = BpkBuilder.generateAreaSpecificPersonIdentifier(baseID, spTargetId);
+
+ } else {
+ log.error(
+ "!!!baseID-element does not include a baseID. This should not be happen any more!!!");
+ sectorSpecId = Pair.newInstance(baseID, baseIdType);
+
+ }
+
+ log.trace("Authenticate user with bPK:" + sectorSpecId.getFirst() + " Type:"
+ + sectorSpecId.getSecond());
+ return sectorSpecId;
+
+ }
+
+ @Deprecated
+ protected IIdentityLink buildOAspecificIdentityLink(final IspConfiguration spConfig,
+ final IIdentityLink idl, final String bpk, final String bpkType)
+ throws EaafConfigurationException, XPathException, DOMException, EaafParserException {
+ if (spConfig.hasBaseIdTransferRestriction()) {
+ log.debug("SP: " + spConfig.getUniqueIdentifier()
+ + " has baseId transfer restriction. Remove baseId from IDL ...");
+ final Element idlassertion = idl.getSamlAssertion();
+ // set bpk/wpbk;
+ final Node prIdentification = XPathUtils.selectSingleNode(idlassertion,
+ SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH);
+ prIdentification.getFirstChild().setNodeValue(bpk);
+ // set bkp/wpbk type
+ final Node prIdentificationType = XPathUtils.selectSingleNode(idlassertion,
+ SimpleIdentityLinkAssertionParser.PERSON_IDENT_TYPE_XPATH);
+ prIdentificationType.getFirstChild().setNodeValue(bpkType);
+
+ final SimpleIdentityLinkAssertionParser idlparser =
+ new SimpleIdentityLinkAssertionParser(idlassertion);
+ return idlparser.parseIdentityLink();
+
+ } else {
+ return idl;
+ }
+
+ }
+
+ /**
+ * Check a bPK-Type against a Service-Provider configuration <br>
+ * If bPK-Type is <code>null</code> the result is <code>false</code>.
+ *
+ * @param oaParam Service-Provider configuration, never null
+ * @param bpkType bPK-Type to check
+ * @return true, if bPK-Type matchs to Service-Provider configuration, otherwise false
+ */
+ @Deprecated
+ protected boolean matchsReceivedBpkToOnlineApplication(final IspConfiguration oaParam,
+ final String bpkType) {
+ return oaParam.getAreaSpecificTargetIdentifier().equals(bpkType);
+
+ }
+
+ /**
+ * Parse information from an IdentityLink into AuthData object.
+ *
+ * @param authData current authentication data
+ * @param identityLink User's identityLink
+ * @param includedGenericSessionData Generic AuthSession Data from PVP attributes
+ */
+ @Deprecated
+ private void parseBasicUserInfosFromIdl(final AuthenticationData authData,
+ final IIdentityLink identityLink, final Collection<String> includedGenericSessionData) {
+ authData.setIdentificationValue(identityLink.getIdentificationValue());
+ authData.setIdentificationType(identityLink.getIdentificationType());
+
+ /*
+ * GivenNames and FamilyNames with simple Apostrophe were escaped with &#39; in
+ * IdentityLinkParser since 5 years. This feature was bug-fix for an SL1.0 AuthBlock problem.
+ * However, the authentication attributes (SAML2, eIDAS, OpenID-Connect) also includes this
+ * escaped values, but there it is not neccesary. We fix this problem in 3.4.3, but the fix can
+ * be deactivated for dependency reasons.
+ */
+ if (basicConfig.getBasicConfigurationBoolean(CONFIG_PROP_ENABLE_IDL_ATTRIBUTE_ESCAPEING,
+ false)) {
+ authData.setGivenName(identityLink.getGivenName().replaceAll("'", "&#39;"));
+ authData.setFamilyName(identityLink.getFamilyName().replaceAll("'", "&#39;"));
+
+ } else {
+ authData.setGivenName(identityLink.getGivenName());
+ authData.setFamilyName(identityLink.getFamilyName());
+
+ }
+
+ authData.setDateOfBirth(identityLink.getDateOfBirth());
+
+
+ // remove corresponding keys from genericSessionData if exists
+ includedGenericSessionData.remove(PVPAttributeDefinitions.PRINCIPAL_NAME_NAME);
+ includedGenericSessionData.remove(PVPAttributeDefinitions.GIVEN_NAME_NAME);
+ includedGenericSessionData.remove(PVPAttributeDefinitions.BIRTHDATE_NAME);
+ includedGenericSessionData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_NAME);
+ includedGenericSessionData.remove(PVPAttributeDefinitions.EID_SOURCE_PIN_TYPE_NAME);
+
+ }
+
+ /**
+ * Get bPK from PVP Attribute 'BPK_NAME', which could be exist in MOASession as 'GenericData'. <br>
+ *
+ * <pre>
+ * <code>session.getGenericDataFromSession(PVPConstants.BPK_NAME, String.class)</code>
+ * </pre>
+ *
+ * @param session MOASession, but never null
+ * @return bPK, which was received by PVP-Attribute, or <code>null</code> if no attribute exists
+ */
+ @Deprecated
+ private String getBpkValueFromPvpAttribute(final IAuthProcessDataContainer session) {
+ String pvpBpkValueAttr =
+ session.getGenericDataFromSession(PVPAttributeDefinitions.BPK_NAME, String.class);
+ if (StringUtils.isNotEmpty(pvpBpkValueAttr)) {
+
+ // fix a wrong bPK-value prefix, which was used in some PVP Standardportal implementations
+ if (pvpBpkValueAttr.startsWith("bPK:")) {
+ log.warn("Attribute " + PVPAttributeDefinitions.BPK_NAME
+ + " contains a not standardize prefix! Staring attribute value correction process ...");
+ pvpBpkValueAttr = pvpBpkValueAttr.substring("bPK:".length());
+
+ }
+
+ final String[] spitted = pvpBpkValueAttr.split(":");
+ if (spitted.length == 2) {
+ log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME);
+ return spitted[1];
+
+
+
+ } else if (spitted.length > 2) {
+ log.warn("Attribute " + PVPAttributeDefinitions.BPK_NAME
+ + " has a wrong encoding and can NOT be USED!" + " Value:" + pvpBpkValueAttr);
+ return null;
+
+ } else {
+ log.debug("Find PVP-Attr: " + PVPAttributeDefinitions.BPK_FRIENDLY_NAME
+ + " without prefix. Use it as it is");
+ return spitted[0];
+
+ }
+
+ }
+
+ return null;
+ }
+
+ /**
+ * Get bPK-Type from PVP Attribute 'EID_SECTOR_FOR_IDENTIFIER_NAME', which could be exist in
+ * MOASession as 'GenericData'. <br>
+ *
+ * <pre>
+ * <code>session.getGenericDataFromSession(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME, String.class)</code>
+ * </pre>
+ *
+ * @param session MOASession, but never null
+ * @return bPKType, which was received by PVP-Attribute, or <code>null</code> if no attribute
+ * exists
+ */
+ @Deprecated
+ private String getBpkTypeFromPvpAttribute(final IAuthProcessDataContainer session) {
+ final String pvpBpkTypeAttr = session.getGenericDataFromSession(
+ PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, String.class);
+
+ if (StringUtils.isNotEmpty(pvpBpkTypeAttr)) {
+ // //fix a wrong bPK-Type encoding, which was used in some PVP Standardportal implementations
+ // if (pvpbPKTypeAttr.startsWith(EAAFConstants.URN_PREFIX_CDID) &&
+ // !pvpbPKTypeAttr.substring(EAAFConstants.URN_PREFIX_CDID.length(),
+ // EAAFConstants.URN_PREFIX_CDID.length() + 1).equals("+")) {
+ // log.warn("Receive uncorrect encoded bBKType attribute " + pvpbPKTypeAttr + " Starting
+ // attribute value correction ... ");
+ // pvpbPKTypeAttr = EAAFConstants.URN_PREFIX_CDID + "+" +
+ // pvpbPKTypeAttr.substring(EAAFConstants.URN_PREFIX_CDID.length() + 1);
+ //
+ // }
+ log.debug(
+ "Find PVP-Attr: " + PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME);
+ return pvpBpkTypeAttr;
+ }
+
+ return null;
+
+
+ /*
+ * INFO: This code could be used to extract the bPKType from 'PVPConstants.BPK_NAME', because
+ * the prefix of BPK_NAME attribute contains the postfix of the bPKType
+ *
+ * Now, all PVP Standardportals should be able to send 'EID_SECTOR_FOR_IDENTIFIER' PVP
+ * attributes
+ */
+ // String pvpbPKValueAttr = session.getGenericDataFromSession(PVPConstants.BPK_NAME,
+ // String.class);
+ // String[] spitted = pvpbPKValueAttr.split(":");
+ // if (MiscUtil.isEmpty(authData.getBPKType())) {
+ // Logger.debug("PVP assertion contains NO bPK/wbPK target attribute. " +
+ // "Starting target extraction from bPK/wbPK prefix ...");
+ // //exract bPK/wbPK type from bpk attribute value prefix if type is
+ // //not transmitted as single attribute
+ // Pattern pattern = Pattern.compile("[a-zA-Z]{2}(-[a-zA-Z]+)?");
+ // Matcher matcher = pattern.matcher(spitted[0]);
+ // if (matcher.matches()) {
+ // //find public service bPK
+ // authData.setBPKType(Constants.URN_PREFIX_CDID + "+" + spitted[0]);
+ // Logger.debug("Found bPK prefix. Set target to " + authData.getBPKType());
+ //
+ // } else {
+ // //find business service wbPK
+ // authData.setBPKType(Constants.URN_PREFIX_WBPK+ "+" + spitted[0]);
+ // Logger.debug("Found wbPK prefix. Set target to " + authData.getBPKType());
+ //
+ // }
+ // }
+
+ }
}