diff options
author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2018-07-20 10:56:04 +0200 |
---|---|---|
committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2018-07-20 10:56:04 +0200 |
commit | 31bc1246bb56fcd8807678e3f7516023bdfaed44 (patch) | |
tree | 0c3ed662a5be943a4ceb70d021e1bb7ac9dc1015 /eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks | |
parent | 2945c875bda2c8236d0b3fd630358fcaca85f4a8 (diff) | |
download | National_eIDAS_Gateway-31bc1246bb56fcd8807678e3f7516023bdfaed44.tar.gz National_eIDAS_Gateway-31bc1246bb56fcd8807678e3f7516023bdfaed44.tar.bz2 National_eIDAS_Gateway-31bc1246bb56fcd8807678e3f7516023bdfaed44.zip |
add SZR client
add different logging backends
define errorcodes and error messages
update to eIDAS Ref. impl 2.1
Diffstat (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks')
3 files changed, 556 insertions, 423 deletions
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java index dfd945c9..b31b6a21 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java @@ -3,41 +3,80 @@ package at.gv.egiz.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 at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; -import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; -import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; -import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; -import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.eIDASAttributeException; -import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; -import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; -import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink; -import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; -import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.DOMUtils; -import at.gv.egovernment.moa.util.XPathUtils; -import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; - -/** +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +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 at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.SZRCommunicationException; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.eIDASAttributeException; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.szr.SZRClient; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.utils.eIDASResponseUtils; +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) */ @@ -46,115 +85,293 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask { HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException { try{ - defaultTaskInitialization(request, executionContext); - - //get eIDAS attributes from MOA-Session - ImmutableAttributeMap eIDASAttributes = moasession.getGenericDataFromSession( - AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST, - ImmutableAttributeMap.class); - - IIdentityLink identityLink = null; - + AuthProcessDataWrapper authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class); + ILightResponse eIDASResponse = authProcessData.getGenericDataFromSession( + Constants.DATA_FULL_EIDAS_RESPONSE, ILightResponse.class); + Map<String, Object> 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 - //TODO: implement SZR-Gateway communication!!!! - if(true) { - + 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 IdentityLinkAssertionParser(idlTemplate).parseIdentityLink(); + identityLink = new SimpleIdentityLinkAssertionParser(idlTemplate).parseIdentityLink(); // replace data Element idlassertion = identityLink.getSamlAssertion(); // - set fake baseID; - Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); - - - Object eIdentifier = eIDASAttributes.getFirstValue( - SAMLEngineUtils.getMapOfAllAvailableAttributes().get( - Constants.eIDAS_ATTR_PERSONALIDENTIFIER)); - if (eIdentifier == null || !(eIdentifier instanceof String)) - throw new eIDASAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); - prIdentification.getFirstChild().setNodeValue((String) eIdentifier); + 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, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); - Object familyName = eIDASAttributes.getFirstValue( - SAMLEngineUtils.getMapOfAllAvailableAttributes().get( - Constants.eIDAS_ATTR_CURRENTFAMILYNAME)); - if (familyName == null || !(familyName instanceof String)) - throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME); - prFamilyName.getFirstChild().setNodeValue((String) familyName); + Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); + prFamilyName.getFirstChild().setNodeValue((String) familyNameObj); // - set first name - Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); - Object givenName = eIDASAttributes.getFirstValue( - SAMLEngineUtils.getMapOfAllAvailableAttributes().get( - Constants.eIDAS_ATTR_CURRENTGIVENNAME)); - if (givenName == null || !(givenName instanceof String)) - throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME); - prGivenName.getFirstChild().setNodeValue((String) givenName); + Node prGivenName = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); + prGivenName.getFirstChild().setNodeValue((String) givenNameObj); // - set date of birth - Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH); - Object dateOfBirth = eIDASAttributes.getFirstValue( - SAMLEngineUtils.getMapOfAllAvailableAttributes().get( - Constants.eIDAS_ATTR_DATEOFBIRTH)); - if (dateOfBirth == null || !(dateOfBirth instanceof DateTime)) - throw new eIDASAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH); - - String formatedDateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirth).toDate()); + 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 IdentityLinkAssertionParser(idlassertion).parseIdentityLink(); + identityLink = new SimpleIdentityLinkAssertionParser(idlassertion).parseIdentityLink(); - //resign IDL - IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance(); - Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), authConfig.getStorkFakeIdLResigningKey()); - identityLink = new IdentityLinkAssertionParser(resignedilAssertion).parseIdentityLink(); - + Pair<String, String> bPKCalc = new BPKBuilder().generateAreaSpecificPersonIdentifier( + identityLink.getIdentificationValue(), + identityLink.getIdentificationType(), + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); + bPK = bPKCalc.getFirst(); + + } else { //contact SZR Gateway - Logger.debug("Starting connecting 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<String, String, String> 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<KeyValueType> 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); + + } - //TODO:!!!!!! + if (bPK == null) { + log.error("ERnB did not return a bPK for target: " + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); + throw new SZRCommunicationException("ernb.01", null); } - Logger.debug("SZR communication was successfull"); + log.debug("ERnB communication was successfull"); + + revisionsLogger.logEvent(pendingReq, -1); + 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()); - if (identityLink == null) { - Logger.error("SZR Gateway did not return an identity link."); - throw new MOAIDException("stork.10", null); - } - revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_IDL_RECEIVED); - moasession.setForeigner(true); - moasession.setIdentityLink(identityLink); - moasession.setBkuURL("Not applicable (eIDASAuthentication)"); - //store MOA-session to database + //store pending-request requestStoreage.storePendingRequest(pendingReq); - + } catch (eIDASAttributeException e) { throw new TaskExecutionException(pendingReq, "Minimum required eIDAS attributeset not found.", e); - } catch (MOAIDException | MOADatabaseException e) { + } catch (EAAFException e) { throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); } catch (Exception e) { - Logger.error("IdentityLink generation for foreign person FAILED.", e); + log.error("IdentityLink generation for foreign person FAILED.", e); throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); } } + private List<KeyValueType> dummyCodeForKeys() { + if (basicConfig.getBasicMOAIDConfigurationBoolean( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_KEYS_USEDUMMY, + false)) { + List<KeyValueType> keyvalueList = new ArrayList<KeyValueType>(); + 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<String, Object> converteIDASAttrToSimpleMap( + ImmutableMap<AttributeDefinition<?>, ImmutableSet<? extends AttributeValue<?>>> attributeMap) { + Map<String, Object> result = new HashMap<String, Object>(); + + 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<String> 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; + } + + } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java index 358b681e..da554249 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java @@ -2,66 +2,64 @@ *******************************************************************************/ package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.Map; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.VelocityEngine; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.saml2.metadata.provider.MetadataProviderException; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.springframework.web.util.UriComponentsBuilder; -import com.google.common.net.MediaType; +import com.google.common.collect.ImmutableSortedSet; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.gui.IGUIFormBuilder; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; +import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eidas.specific.connector.gui.StaticGuiBuilderConfiguration; import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants; -import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; -import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; -import at.gv.egovernment.moa.id.auth.frontend.velocity.VelocityProvider; -import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; -import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; -import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; -import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; -import at.gv.egovernment.moa.id.commons.api.IRequest; -import at.gv.egovernment.moa.id.commons.api.data.CPEPS; -import at.gv.egovernment.moa.id.commons.api.data.StorkAttribute; -import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; -import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; -import eu.eidas.auth.commons.EidasStringUtil; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.eIDASAuthenticationException; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.service.eIDASAttributeRegistry; +import eu.eidas.auth.commons.EidasParameterKeys; import eu.eidas.auth.commons.attribute.AttributeDefinition; -import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder; -import eu.eidas.auth.commons.light.impl.LightRequest; import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; -import eu.eidas.auth.commons.protocol.IRequestMessage; -import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance; -import eu.eidas.auth.commons.protocol.eidas.LevelOfAssuranceComparison; +import eu.eidas.auth.commons.light.ILightRequest; +import eu.eidas.auth.commons.light.impl.LightRequest; import eu.eidas.auth.commons.protocol.eidas.SpType; -import eu.eidas.auth.commons.protocol.eidas.impl.EidasAuthenticationRequest; +import eu.eidas.auth.commons.tx.BinaryLightToken; +import eu.eidas.specificcommunication.BinaryLightTokenHelper; +import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames; +import eu.eidas.specificcommunication.exception.SpecificCommunicationException; +import eu.eidas.specificcommunication.protocol.impl.SpecificConnectorCommunicationServiceImpl; /** * @author tlenz * - */ -@Component("GenerateAuthnRequestTask") + */ +@Component("ConnecteIDASNodeTask") public class GenerateAuthnRequestTask extends AbstractAuthServletTask { - - /* (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) - */ + private static final Logger log = LoggerFactory.getLogger(GenerateAuthnRequestTask.class); + + @Autowired IConfiguration basicConfig; + @Autowired eIDASAttributeRegistry attrRegistry; + @Autowired ApplicationContext context; + @Autowired ITransactionStorage transactionStore; + @Autowired IGUIFormBuilder guiBuilder; + @Override public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) @@ -69,245 +67,196 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask { try{ //get service-provider configuration - IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration(); + ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); // get target and validate citizen countryCode - String citizenCountryCode = (String) executionContext.get(MOAIDAuthConstants.PARAM_CCC); + String citizenCountryCode = (String) executionContext.get(Constants.EXECUTIONCONTEXT_SELECTED_COUNTRY); if (StringUtils.isEmpty(citizenCountryCode)) { // illegal state; task should not have been executed without a selected country - throw new AuthenticationException("eIDAS.03", new Object[] { "" }); + throw new eIDASAuthenticationException("eidas.03", new Object[] { "" }); } - CPEPS cpeps = authConfig.getStorkConfig().getCPEPSWithFullName(citizenCountryCode); - if(null == cpeps) { - Logger.error("PEPS unknown for country: " + citizenCountryCode); - throw new AuthenticationException("eIDAS.04", new Object[] {citizenCountryCode}); - } - Logger.debug("Found eIDaS Node/C-PEPS configuration for citizen of country: " + citizenCountryCode); - - //TODO: load authnReq End-Point URL from configuration - SingleSignOnService authnReqEndpoint = null; + //TODO: maybe add countryCode validation before request ref. impl. eIDAS node + log.debug("Request eIDAS auth. for citizen of country: " + citizenCountryCode); - + //TODO: switch to entityID and set new status codes -// revisionsLogger.logEvent(oaConfig, pendingReq, -// MOAIDEventConstants.AUTHPROCESS_PEPS_SELECTED, -// metadataUrl); + //revisionsLogger.logEvent(oaConfig, pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_SELECTED, metadataUrl); - // assemble requested attributes - Collection<StorkAttribute> attributesFromConfig = oaConfig.getRequestedSTORKAttributes(); - - // - prepare attribute list - - // - fill container - List<AttributeDefinition<?>> reqAttrList = new ArrayList<AttributeDefinition<?>>(); - //TODO: update requested attribute builder -// for (StorkAttribute current : attributesFromConfig) { -// AttributeDefinition<?> newAttribute = SAMLEngineUtils.getMapOfAllAvailableAttributes().get(current.getName()); -// -// if (newAttribute == null) { -// Logger.warn("eIDAS attribute with friendlyName:" + current.getName() + " is not supported."); -// -// } else { -// boolean globallyMandatory = false; -// for (StorkAttribute currentGlobalAttribute : authConfig.getStorkConfig().getStorkAttributes()) -// if (current.getName().equals(currentGlobalAttribute.getName())) { -// globallyMandatory = BooleanUtils.isTrue(currentGlobalAttribute.getMandatory()); -// break; -// } -// -// Builder<?> attrBuilder = AttributeDefinition.builder(newAttribute).required(current.getMandatory() || globallyMandatory); -// reqAttrList.add(attrBuilder.build()); -// -// } -// } - - //request -// if (reqAttrList.isEmpty()) { -// Logger.info("No attributes requested by OA:" + pendingReq.getOnlineApplicationConfiguration().getPublicURLPrefix() -// + " --> Request attr:" + Constants.eIDAS_ATTR_PERSONALIDENTIFIER + " by default"); -// AttributeDefinition<?> newAttribute = SAMLEngineUtils.getMapOfAllAvailableAttributes().get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); -// Builder<?> attrBuilder = AttributeDefinition.builder(newAttribute).required(true); -// reqAttrList.add(attrBuilder.build()); -// -// } - - //build requested attribute set - ImmutableAttributeMap reqAttrMap = new ImmutableAttributeMap.Builder().putAll(reqAttrList).build(); //build eIDAS AuthnRequest - LightRequest.Builder authnRequestBuilder = LightRequest.builder(); - + LightRequest.Builder authnRequestBuilder = LightRequest.builder(); authnRequestBuilder.id(UUID.randomUUID().toString()); - authnRequestBuilder.providerName(pendingReq.getAuthURL()); - String issur = pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA; - authnRequestBuilder.issuer(issur); - //TODO: - //authnRequestBuilder.destination(authnReqEndpoint.getLocation()); - - authnRequestBuilder.nameIdFormat(Constants.eIDAS_REQ_NAMEID_FORMAT); + String issur = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_ENTITYID); + if (StringUtils.isEmpty(issur)) { + log.error("Found NO 'eIDAS node issuer' in configuration. Authentication NOT possible!"); + throw new EAAFConfigurationException("Found NO 'eIDAS node issuer' in configuration. Authentication NOT possible!"); + + } + authnRequestBuilder.issuer(issur); - //set minimum required eIDAS LoA from OA config - String LoA = oaConfig.getQaaLevel(); - //TODO: -// if (MiscUtil.isNotEmpty(LoA)) -// authnRequestBuilder.levelOfAssurance(LevelOfAssurance.fromString(oaConfig.getQaaLevel())); -// else - authnRequestBuilder.levelOfAssurance(LevelOfAssurance.HIGH.getValue()); - //TODO: check if required - //authnRequestBuilder.levelOfAssuranceComparison(LevelOfAssuranceComparison.MINIMUM); + //TODO: set matching mode if eIDAS ref. impl. support this method + + //TODO: update if eIDAS ref. impl. supports exact matching for non-notified LoA schemes + String loa = EAAFConstants.EIDAS_LOA_HIGH; + if (spConfig.getRequiredLoA() != null) { + if (spConfig.getRequiredLoA().isEmpty()) + log.info("No eIDAS LoA requested. Use LoA HIGH as default"); + + else { + if (spConfig.getRequiredLoA().size() > 1 ) + log.info("Currently only ONE requested LoA is supported for service provider. Use first one ... "); + + loa = spConfig.getRequiredLoA().get(0); + + } + } + + log.debug("Request eIdAS node with LoA: " + loa); + authnRequestBuilder.levelOfAssurance(loa); - //set correct SPType for this online application - if (oaConfig.hasBaseIdTransferRestriction()) - authnRequestBuilder.spType(SpType.PRIVATE.getValue()); - else + //set correct SPType for requested target sector + String publicSectorTargetSelector = basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_NODE_PUBLICSECTOR_TARGETS, + Constants.POLICY_DEFAULT_ALLOWED_TARGETS); + Pattern p = Pattern.compile(publicSectorTargetSelector); + Matcher m = p.matcher(spConfig.getAreaSpecificTargetIdentifier()); + if (m.matches()) { + log.debug("Map " + spConfig.getAreaSpecificTargetIdentifier() + " to 'PublicSector'"); authnRequestBuilder.spType(SpType.PUBLIC.getValue()); + + //TODO: only for eIDAS ref. node 2.0 because it need 'Providername' for any SPType + String providerName = pendingReq.getRawData(Constants.DATA_PROVIDERNAME, String.class); + if (StringUtils.isNotEmpty(providerName) + && basicConfig.getBasicMOAIDConfigurationBoolean( + Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_ADD_ALWAYS_PROVIDERNAME, + false) + ) + authnRequestBuilder.providerName(providerName); + + } else { + log.debug("Map " + spConfig.getAreaSpecificTargetIdentifier() + " to 'PrivateSector'"); + authnRequestBuilder.spType(SpType.PRIVATE.getValue()); + //TODO: switch to RequesterId in further version + //set provider name for private sector applications + String providerName = pendingReq.getRawData(Constants.DATA_PROVIDERNAME, String.class); + if (StringUtils.isNotEmpty(providerName)) + authnRequestBuilder.providerName(providerName); - //TODO - //set service provider (eIDAS node) countryCode -// authnRequestBuilder.serviceProviderCountryCode( -// authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT")); - - //set citizen country code for foreign uses - authnRequestBuilder.citizenCountryCode(cpeps.getCountryCode()); - - //add requested attributes - authnRequestBuilder.requestedAttributes(reqAttrMap); - + } - LightRequest lightAuthnReq = authnRequestBuilder.build(); + //set nameIDFormat + authnRequestBuilder.nameIdFormat(Constants.eIDAS_REQ_NAMEID_FORMAT); + //set citizen country code for foreign uses + authnRequestBuilder.citizenCountryCode(citizenCountryCode); + //set relay state + authnRequestBuilder.relayState(pendingReq.getPendingRequestId()); - //IRequestMessage authnRequest = engine.generateRequestMessage(authnRequestBuilder.build(), issur); + //build and add requested attribute set + ImmutableAttributeMap reqAttrMap = translateToEidasAttributes(attrRegistry.getAttributeSetFromConfiguration()); + authnRequestBuilder.requestedAttributes(reqAttrMap); - //encode AuthnRequest -// byte[] token = authnRequest.getMessageBytes(); -// String SAMLRequest = EidasStringUtil.encodeToBase64(token); + //build request + LightRequest lightAuthnReq = authnRequestBuilder.build(); + //put request into cache + BinaryLightToken token = putRequestInCommunicationCache(lightAuthnReq); + final String tokenBase64 = BinaryLightTokenHelper.encodeBinaryLightTokenBase64(token); + + //Workaround, because eIDAS node ref. impl. does not return relayState + if (basicConfig.getBasicMOAIDConfigurationBoolean( + Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_USEREQUESTIDASTRANSACTIONIDENTIFIER, + false)) { + log.trace("Put lightRequestId into transactionstore as session-handling backup"); + transactionStore.put(lightAuthnReq.getId(), pendingReq.getPendingRequestId(), -1); + + } -// if (SAMLConstants.SAML2_POST_BINDING_URI.equals(authnReqEndpoint.getBinding())) -// buildPostBindingRequest(pendingReq, authnReqEndpoint, SAMLRequest, authnRequest, response); -// -// //TODO: redirect Binding is not completely implemented -// //else if (SAMLConstants.SAML2_REDIRECT_BINDING_URI.equals(authnReqEndpoint.getBinding())) -// //buildRedirecttBindingRequest(pendingReq, authnReqEndpoint, token, authnRequest, response); -// -// else { -// Logger.error("eIDAS-node use an unsupported binding (" -// + authnReqEndpoint.getBinding() + "). Request eIDAS node not possible."); -// throw new MOAIDException("eIDAS.02", new Object[]{"eIDAS-node use an unsupported binding"}); -// -// } + if (basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_METHOD, + Constants.FORWARD_METHOD_GET + ).equals(Constants.FORWARD_METHOD_GET)) { + + log.debug("Use http-redirect for eIDAS node forwarding ... "); + //send redirect + UriComponentsBuilder redirectUrl = UriComponentsBuilder.fromHttpUrl(basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_URL)); + redirectUrl.queryParam(EidasParameterKeys.TOKEN.toString(), tokenBase64); + response.sendRedirect(redirectUrl.build().encode().toString()); + + } else { + log.debug("Use http-post for eIDAS node forwarding ... "); + StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration( + basicConfig, + pendingReq, + Constants.TEMPLATE_POST_FORWARD_NAME, + null); + + config.putCustomParameter(Constants.TEMPLATE_POST_FORWARD_ENDPOINT, + basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_URL)); + config.putCustomParameter(Constants.TEMPLATE_POST_FORWARD_TOKEN_NAME, + EidasParameterKeys.TOKEN.toString()); + config.putCustomParameter(Constants.TEMPLATE_POST_FORWARD_TOKEN_VALUE, + tokenBase64); + + guiBuilder.build(response, config, "BKU-Selection form"); + + } - - -// }catch (EIDASSAMLEngineException e){ -// throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.", -// new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e)); - } catch (MOAIDException e) { + + } catch (eIDASAuthenticationException e) { throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.", e); } catch (Exception e) { - Logger.error("eIDAS AuthnRequest generation FAILED.", e); + log.warn("eIDAS AuthnRequest generation FAILED.", e); throw new TaskExecutionException(pendingReq, e.getMessage(), e); } + } + + private ImmutableAttributeMap translateToEidasAttributes(final Map<String, Boolean> requiredAttributes) { + ImmutableAttributeMap.Builder builder = ImmutableAttributeMap.builder(); + for (Map.Entry<String,Boolean> attribute : requiredAttributes.entrySet()) { + final String name = attribute.getKey(); + final ImmutableSortedSet<AttributeDefinition<?>> byFriendlyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(name); + if (!byFriendlyName.isEmpty()) { + final AttributeDefinition<?> attributeDefinition = byFriendlyName.first(); + builder.put(AttributeDefinition.builder(attributeDefinition).required(attribute.getValue()).build()); + + } else + log.warn("Can NOT request UNKNOWN attribute: " + attribute.getKey() + " Ignore it!"); + + } + + return builder.build(); + + } - /** - * Encode the eIDAS request with POST binding - * - * @param pendingReq - * @param authnReqEndpoint - * @param SAMLRequest - * @param authnRequest - * @param response - * @throws MOAIDException - */ - private void buildPostBindingRequest(IRequest pendingReq, SingleSignOnService authnReqEndpoint, - String SAMLRequest, IRequestMessage authnRequest, HttpServletResponse response) - throws MOAIDException { - //send + private BinaryLightToken putRequestInCommunicationCache(ILightRequest iLightRequest) throws ServletException { + final BinaryLightToken binaryLightToken; try { - VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); - Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm"); - VelocityContext context = new VelocityContext(); - - String actionType = "SAMLRequest"; - context.put(actionType, SAMLRequest); - context.put("RelayState", pendingReq.getRequestID()); - context.put("action", authnReqEndpoint.getLocation()); - - Logger.debug("Using SingleSignOnService url as action: " + authnReqEndpoint.getLocation()); - Logger.debug("Encoded " + actionType + " original: " + SAMLRequest); + final SpecificConnectorCommunicationServiceImpl springManagedSpecificConnectorCommunicationService = + (SpecificConnectorCommunicationServiceImpl) context.getBean(SpecificCommunicationDefinitionBeanNames.SPECIFIC_CONNECTOR_COMMUNICATION_SERVICE.toString()); - Logger.trace("Starting template merge"); - StringWriter writer = new StringWriter(); - - Logger.trace("Doing template merge"); - template.merge(context, writer); - - Logger.trace("Template merge done"); - Logger.trace("Sending html content: " + writer.getBuffer().toString()); + binaryLightToken = springManagedSpecificConnectorCommunicationService.putRequest(iLightRequest); - - byte[] content = writer.getBuffer().toString().getBytes("UTF-8"); - response.setContentType(MediaType.HTML_UTF_8.toString()); - response.setContentLength(content.length); - response.getOutputStream().write(content); - - revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq, - MOAIDEventConstants.AUTHPROCESS_PEPS_REQUESTED, - authnRequest.getRequest().getId()); - - } catch (Exception e) { - Logger.error("Velocity general error: " + e.getMessage()); - throw new MOAIDException("eIDAS.02", new Object[]{e.getMessage()}, e); + } catch (SpecificCommunicationException e) { + log.error("Unable to process specific request"); + throw new ServletException(e); } - - } - - /** - * Select a SingleSignOnService endPoint from eIDAS node metadata. - * This endPoint receives the Authn. request - * - * @param idpEntity - * @return - */ - private SingleSignOnService selectSingleSignOnServiceFromMetadata(EntityDescriptor idpEntity) { - //select SingleSignOn Service endpoint from IDP metadata - SingleSignOnService endpoint = null; - if (idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) == null) { - return null; - - } - - for (SingleSignOnService sss : - idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { - - // use POST binding as default if it exists - if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) - endpoint = sss; - - //TODO: redirect Binding is not completely implemented - // use Redirect binding as backup -// else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) -// && endpoint == null ) -// endpoint = sss; - - } - - return endpoint; - } - + + return binaryLightToken; + } + } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java index 055c402f..f0b37ede 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java @@ -5,84 +5,78 @@ package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.opensaml.saml2.core.StatusCode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; -import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; -import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; -import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; -import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; -import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; -import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; -import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASResponseNotSuccessException; -import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; -import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; -import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.protocols.eidas.validator.eIDASResponseValidator; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; -import eu.eidas.auth.commons.EidasStringUtil; -import eu.eidas.auth.commons.protocol.IAuthenticationResponse; -import eu.eidas.auth.engine.ProtocolEngineI; -import eu.eidas.engine.exceptions.EIDASSAMLEngineException; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +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.idp.auth.data.AuthProcessDataWrapper; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.eIDASAuthenticationException; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.service.eIDASAttributeRegistry; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.validator.eIDASResponseValidator; +import eu.eidas.auth.commons.light.ILightResponse; -@Component("ReceiveAuthnResponseTask") +@Component("ReceiveResponseFromeIDASNodeTask") public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { - - @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider; + private static final Logger log = LoggerFactory.getLogger(ReceiveAuthnResponseTask.class); - @Override + @Autowired private ApplicationContext context; + @Autowired private IConfiguration basicConfig; + @Autowired private eIDASAttributeRegistry attrRegistry; + + @Override public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException { - - try{ - //get SAML Response - String base64SamlToken = request.getParameter("SAMLResponse"); - if (MiscUtil.isEmpty(base64SamlToken)) { - Logger.warn("No eIDAS SAMLReponse found in http request."); - throw new MOAIDException("HTTP request includes no eIDAS SAML-Response element.", null); + try{ + +// //get token from Request +// final String tokenBase64 = request.getParameter(EidasParameterKeys.TOKEN.toString()); +// if (StringUtils.isEmpty(tokenBase64)) { +// log.warn("NO eIDAS message token found."); +// throw new eIDASAuthenticationException("TODO", null, +// "NO eIDAS message token found."); +// +// } +// +// //get eIDAS response from cache +// final SpecificConnectorCommunicationServiceImpl specificConnectorCommunicationService = +// (SpecificConnectorCommunicationServiceImpl) context.getBean(SpecificCommunicationDefinitionBeanNames.SPECIFIC_CONNECTOR_COMMUNICATION_SERVICE.toString()); +// ILightResponse eIDASResponse = specificConnectorCommunicationService.getAndRemoveResponse(tokenBase64, +// ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes())); + + ILightResponse eIDASResponse = (ILightResponse) request.getAttribute(Constants.DATA_FULL_EIDAS_RESPONSE); + if (eIDASResponse == null) { + log.warn("NO eIDAS response-message found."); + throw new eIDASAuthenticationException("eidas.01", null); } - //get MOASession - defaultTaskInitialization(request, executionContext); + log.debug("Receive eIDAS response with RespId:" + eIDASResponse.getId() + " for ReqId:" + eIDASResponse.getInResponseToId()); - //decode SAML response - byte[] decSamlToken = EidasStringUtil.decodeBytesFromBase64(base64SamlToken); - - //get eIDAS SAML-engine - ProtocolEngineI engine = SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); - - //validate SAML token - IAuthenticationResponse samlResp = engine.unmarshallResponseAndValidate(decSamlToken, - request.getRemoteHost(), - Constants.CONFIG_PROPS_SKEWTIME_BEFORE, - Constants.CONFIG_PROPS_SKEWTIME_AFTER, - pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA); - - if (samlResp.isEncrypted()) { - Logger.info("Received encrypted eIDAS SAML-Response."); - //TODO: check if additional decryption operation is required - - } - - - //check response StatusCode - if (!samlResp.getStatusCode().equals(StatusCode.SUCCESS_URI)) { - Logger.info("Receice eIDAS Response with StatusCode:" + samlResp.getStatusCode() - + " Subcode:" + samlResp.getSubStatusCode() + " Msg:" + samlResp.getStatusMessage()); - throw new EIDASResponseNotSuccessException("eIDAS.11", new Object[]{samlResp.getStatusMessage()}); + + //check response StatusCode + if (!eIDASResponse.getStatus().getStatusCode().equals(Constants.SUCCESS_URI)) { + log.info("Receice eIDAS Response with StatusCode:" + eIDASResponse.getStatus().getStatusCode() + + " Subcode:" + eIDASResponse.getStatus().getSubStatusCode() + " Msg:" + eIDASResponse.getStatus().getStatusMessage()); + throw new eIDASAuthenticationException("eidas.02", new Object[]{eIDASResponse.getStatus().getStatusCode(), eIDASResponse.getStatus().getStatusMessage()}); } + // extract all Attributes from response + + + // ********************************************************** - // ******* MOA-ID specific response validation ********** + // ******* MS-specificresponse validation ********** // ********************************************************** - String spCountry = authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT"); - eIDASResponseValidator.validateResponse(pendingReq, samlResp, spCountry); + String spCountry = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT"); + eIDASResponseValidator.validateResponse(pendingReq, eIDASResponse, spCountry, attrRegistry); // ********************************************************** @@ -90,51 +84,24 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { // ********************************************************** //update MOA-Session data with received information - Logger.debug("Store eIDAS response information into MOA-session."); - - moasession.setQAALevel(samlResp.getLevelOfAssurance()); - - moasession.setGenericDataToSession( - AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST, - samlResp.getAttributes()); - - moasession.setGenericDataToSession( - AuthenticationSessionStorageConstants.eIDAS_RESPONSE, - decSamlToken); + log.debug("Store eIDAS response information into pending-request."); + AuthProcessDataWrapper authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class); + authProcessData.setQAALevel(eIDASResponse.getLevelOfAssurance()); + authProcessData.setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, eIDASResponse); - //set issuer nation as PVP attribute into MOASession - moasession.setGenericDataToSession(PVPConstants.EID_ISSUING_NATION_NAME, samlResp.getCountry()); - //store MOA-session to database requestStoreage.storePendingRequest(pendingReq); - revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq, - MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED, - samlResp.getId()); + revisionsLogger.logEvent(pendingReq, -1, eIDASResponse.getId()); - } catch (MOAIDException e) { + } catch (EAAFException e) { throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", e); - - }catch (EIDASSAMLEngineException e) { - Logger.warn("eIDAS Response validation FAILED.", e); - Logger.debug("eIDAS response was: " + request.getParameter("SAMLResponse")); - revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq, - MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR); - throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", - new EIDASEngineException("eIDAS.09", new Object[]{e.getMessage()}, e)); - } catch (MOADatabaseException e) { - revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq, - MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR); - throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", - new MOAIDException("init.04", new Object[]{""}, e)); - } catch (Exception e) { - Logger.warn("eIDAS Response processing FAILED.", e); - revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq, - MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR); + log.warn("eIDAS Response processing FAILED.", e); + revisionsLogger.logEvent(pendingReq, -1); throw new TaskExecutionException(pendingReq, e.getMessage(), - new MOAIDException("eIDAS.10", new Object[]{e.getMessage()}, e)); + new eIDASAuthenticationException("eidas.05", new Object[]{e.getMessage()}, e)); } |