diff options
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.java | 1443 |
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 ' - * 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("'", "'")); - authData.setFamilyName(identityLink.getFamilyName().replaceAll("'", "'")); - - } 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 ' 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("'", "'")); + authData.setFamilyName(identityLink.getFamilyName().replaceAll("'", "'")); + + } 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()); + // + // } + // } + + } } |