From 6d09f43225ba2e0f6d7b0583f843c858a1015807 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 26 Jul 2018 10:30:14 +0200 Subject: namespace refactoring --- .../tasks/CreateIdentityLinkTask.java | 380 +++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java new file mode 100644 index 00000000..c5d33b73 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java @@ -0,0 +1,380 @@ +/******************************************************************************* + *******************************************************************************/ +package at.asitplus.eidas.specific.modules.authmodule_eIDASv2.tasks; + +import java.io.InputStream; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.Base64Utils; +import org.w3._2000._09.xmldsig.KeyValueType; +import org.w3._2000._09.xmldsig.RSAKeyValueType; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +import at.asitplus.eidas.specific.connector.MSConnectorEventCodes; +import at.asitplus.eidas.specific.modules.authmodule_eIDASv2.Constants; +import at.asitplus.eidas.specific.modules.authmodule_eIDASv2.exception.SZRCommunicationException; +import at.asitplus.eidas.specific.modules.authmodule_eIDASv2.exception.eIDASAttributeException; +import at.asitplus.eidas.specific.modules.authmodule_eIDASv2.szr.SZRClient; +import at.asitplus.eidas.specific.modules.authmodule_eIDASv2.utils.eIDASResponseUtils; +import at.gv.e_government.reference.namespace.persondata._20020228.PersonNameType; +import at.gv.e_government.reference.namespace.persondata._20020228.PhysicalPersonType; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.data.Trible; +import at.gv.egiz.eaaf.core.impl.idp.auth.builder.BPKBuilder; +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.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eaaf.core.impl.utils.DOMUtils; +import at.gv.egiz.eaaf.core.impl.utils.XPathUtils; +import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.AttributeValue; +import eu.eidas.auth.commons.light.ILightResponse; +import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress; +import szrservices.IdentityLinkType; +import szrservices.PersonInfoType; +import szrservices.TravelDocumentType; + +/** + * @author tlenz + * + */ +@Component("CreateIdentityLinkTask") +public class CreateIdentityLinkTask extends AbstractAuthServletTask { + private static final Logger log = LoggerFactory.getLogger(CreateIdentityLinkTask.class); + + //@Autowired private eIDASAttributeRegistry attrRegistry; + @Autowired private IConfiguration basicConfig; + @Autowired private SZRClient szrClient; + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, + HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try{ + AuthProcessDataWrapper authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class); + ILightResponse eIDASResponse = authProcessData.getGenericDataFromSession( + Constants.DATA_FULL_EIDAS_RESPONSE, ILightResponse.class); + Map simpleAttrMap = converteIDASAttrToSimpleMap(eIDASResponse.getAttributes().getAttributeMap()); + + IIdentityLink identityLink = null; + String bPK = null; + + //extract attributes + Object eIdentifierObj = simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); + Object familyNameObj = simpleAttrMap.get(Constants.eIDAS_ATTR_CURRENTFAMILYNAME); + Object givenNameObj = simpleAttrMap.get(Constants.eIDAS_ATTR_CURRENTGIVENNAME); + Object dateOfBirthObj = simpleAttrMap.get(Constants.eIDAS_ATTR_DATEOFBIRTH); + + //check if availabe + if (eIdentifierObj == null || !(eIdentifierObj instanceof String)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); + + if (familyNameObj == null || !(familyNameObj instanceof String)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME); + + if (givenNameObj == null || !(givenNameObj instanceof String)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME); + + if (dateOfBirthObj == null || !(dateOfBirthObj instanceof DateTime)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH); + + //connect SZR-Gateway + if(basicConfig.getBasicMOAIDConfigurationBoolean( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USEDUMMY, false)) { + log.warn("SZR-Dummy IS ACTIVE! IdentityLink is NOT VALID!!!!"); + // create fake IdL + // - fetch IdL template from resources + InputStream s = CreateIdentityLinkTask.class.getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml"); + Element idlTemplate = DOMUtils.parseXmlValidating(s); + + identityLink = new SimpleIdentityLinkAssertionParser(idlTemplate).parseIdentityLink(); + + // replace data + Element idlassertion = identityLink.getSamlAssertion(); + + // - set fake baseID; + Node prIdentification = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); + prIdentification.getFirstChild().setNodeValue((String) eIdentifierObj); + + //build personal identifier which looks like a baseID +// String fakeBaseID = new BPKBuilder().buildBPK(eIdentifier, "baseID"); +// Logger.info("Map eIDAS eIdentifier:" + eIdentifier + " to fake baseID:" + fakeBaseID); +// prIdentification.getFirstChild().setNodeValue(fakeBaseID); + + // - set last name + Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); + prFamilyName.getFirstChild().setNodeValue((String) familyNameObj); + + // - set first name + Node prGivenName = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); + prGivenName.getFirstChild().setNodeValue((String) givenNameObj); + + // - set date of birth + Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH); + String formatedDateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirthObj).toDate()); + prDateOfBirth.getFirstChild().setNodeValue(formatedDateOfBirth); + + identityLink = new SimpleIdentityLinkAssertionParser(idlassertion).parseIdentityLink(); + + Pair bPKCalc = new BPKBuilder().generateAreaSpecificPersonIdentifier( + identityLink.getIdentificationValue(), + identityLink.getIdentificationType(), + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); + bPK = bPKCalc.getFirst(); + + + } else { + //contact SZR Gateway + log.debug("Starting connecting SZR Gateway"); + PersonInfoType personInfo = new PersonInfoType(); + PersonNameType personName = new PersonNameType(); + PhysicalPersonType naturalPerson = new PhysicalPersonType(); + TravelDocumentType eDocument = new TravelDocumentType(); + + naturalPerson.setName(personName ); + personInfo.setPerson(naturalPerson ); + personInfo.setTravelDocument(eDocument ); + + //parse some eID attributes + String dateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirthObj).toDate()); + Trible eIdentifier = + eIDASResponseUtils.parseEidasPersonalIdentifier((String)eIdentifierObj); + String uniqueId = (String)eIdentifierObj; + String citizenCountry = eIdentifier.getFirst(); + + //person information + personName.setFamilyName((String)familyNameObj); + personName.setGivenName((String)givenNameObj); + naturalPerson.setDateOfBirth(dateOfBirth); + eDocument.setIssuingCountry(citizenCountry); + eDocument.setDocumentNumber(uniqueId); + + //eID document information + eDocument.setDocumentType(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE, + Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE)); + + //TODO: that should be removed + eDocument.setIssueDate(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_ISSUING_DATE, + Constants.SZR_CONSTANTS_DEFAULT_ISSUING_DATE)); + eDocument.setIssuingAuthority(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_ISSUING_AUTHORITY, + Constants.SZR_CONSTANTS_DEFAULT_ISSUING_AUTHORITY)); + + //TODO: keys are not available in eIDAS + List keyValue = dummyCodeForKeys(); + + /*TODO: + * Validate if IDL signature is valid after using this method + * MAYBE we had to switch to 'getIdentityLinkInRawMode' method! + */ + IdentityLinkType result = szrClient.getIdentityLink( + personInfo, + keyValue, + basicConfig.getBasicMOAIDConfigurationBoolean( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_INSERTERNB, + true) + ); + + Element idlFromSZR = (Element)result.getAssertion(); + identityLink = new SimpleIdentityLinkAssertionParser(idlFromSZR).parseIdentityLink(); + + + //get bPK from SZR + bPK = szrClient.getBPK( + personInfo, + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(), + basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ, + "no VKZ defined")); + + } + + if (identityLink == null) { + log.error("ERnB did not return an identity link."); + throw new SZRCommunicationException("ernb.00", null); + + } + revisionsLogger.logEvent(pendingReq, MSConnectorEventCodes.SZR_IDL_RECEIVED); + + + if (bPK == null) { + log.error("ERnB did not return a bPK for target: " + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); + throw new SZRCommunicationException("ernb.01", null); + + } + revisionsLogger.logEvent(pendingReq, MSConnectorEventCodes.SZR_BPK_RECEIVED); + + log.debug("ERnB communication was successfull"); + + authProcessData.setForeigner(true); + authProcessData.setIdentityLink(identityLink); + authProcessData.setGenericDataToSession( + PVPAttributeDefinitions.EID_ISSUING_NATION_NAME, + eIDASResponseUtils.parseEidasPersonalIdentifier((String) simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER)).getFirst()); + + //set bPK and bPKType into auth session + authProcessData.setGenericDataToSession( + PVPAttributeDefinitions.BPK_NAME, + extendBPKbyPrefix( + bPK, + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()) + ); + authProcessData.setGenericDataToSession( + PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); + + + + //store pending-request + requestStoreage.storePendingRequest(pendingReq); + + } catch (eIDASAttributeException e) { + throw new TaskExecutionException(pendingReq, "Minimum required eIDAS attributeset not found.", e); + + } catch (EAAFException e) { + throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); + + } catch (Exception e) { + log.error("IdentityLink generation for foreign person FAILED.", e); + throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); + + } + } + + private List dummyCodeForKeys() { + if (basicConfig.getBasicMOAIDConfigurationBoolean( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_KEYS_USEDUMMY, + false)) { + List keyvalueList = new ArrayList(); + try { + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Constants.SZR_CONSTANTS_DEFAULT_PUBL_KEY); + KeyFactory kf = KeyFactory.getInstance("RSA"); + + PublicKey pb = kf.generatePublic(spec); + + RSAPublicKey rsapb = (RSAPublicKey)pb; + BigInteger modulus = rsapb.getModulus(); + BigInteger exponent = rsapb.getPublicExponent(); + + // set key values + RSAKeyValueType rsa = new RSAKeyValueType(); + rsa.setExponent(new String(Base64Utils.encode(exponent.toByteArray()))); + rsa.setModulus(new String(Base64Utils.encode(modulus.toByteArray()))); + + KeyValueType key = new KeyValueType(); + key.setRSAKeyValue(rsa); + + keyvalueList.add(key); + + return keyvalueList; + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + log.error("TestCode has an internal ERROR", e); + + } + + } + + return null; + + } + + private String extendBPKbyPrefix(String bpk, String type) { + String bPKType = null; + + if (type.startsWith(EAAFConstants.URN_PREFIX_WBPK)) + bPKType = type.substring((EAAFConstants.URN_PREFIX_WBPK).length()); + + else if (type.startsWith(EAAFConstants.URN_PREFIX_CDID)) + bPKType = type.substring((EAAFConstants.URN_PREFIX_CDID).length()); + + else if (type.startsWith(EAAFConstants.URN_PREFIX_EIDAS)) + bPKType = type.substring((EAAFConstants.URN_PREFIX_EIDAS).length()); + + + if (bPKType != null ) { + log.trace("Authenticate user with bPK/wbPK " + bpk + " and Type=" + bPKType); + return bPKType + ":" + bpk; + + } else { + log.warn("Service Provider Target with: " + type + " is NOT supported. Set bPK as it is ..."); + return bpk; + + } + + } + + //TODO: update for complexe attributes + private Map converteIDASAttrToSimpleMap( + ImmutableMap, ImmutableSet>> attributeMap) { + Map result = new HashMap(); + + for (AttributeDefinition el : attributeMap.keySet()) { + + final Class parameterizedType = el.getParameterizedType(); + if ((DateTime.class).equals(parameterizedType)) { + DateTime attribute = eIDASResponseUtils.translateDateAttribute(el, attributeMap.get(el).asList()); + if (attribute != null) + result.put(el.getFriendlyName(), attribute); + else + log.info("Ignore empty 'DateTime' attribute"); + + } else if ((PostalAddress.class).equals(parameterizedType)) { + PostalAddress addressAttribute = eIDASResponseUtils.translateAddressAttribute(el, attributeMap.get(el).asList()); + if (addressAttribute != null) + result.put(el.getFriendlyName(), addressAttribute); + else + log.info("Ignore empty 'PostalAddress' attribute"); + + } else { + List natPersonIdObj = eIDASResponseUtils.translateStringListAttribute(el, attributeMap.get(el).asList()); + String stringAttr = natPersonIdObj.get(0); + if (StringUtils.isNotEmpty(stringAttr)) + result.put(el.getFriendlyName(), stringAttr); + else + log.info("Ignore empty 'String' attribute"); + + } + } + + return result; + } + + +} -- cgit v1.2.3