diff options
author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2018-06-26 11:06:20 +0200 |
---|---|---|
committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2018-06-26 11:06:20 +0200 |
commit | ae550884f5467f6ff6df23100686bc54e100d2d4 (patch) | |
tree | cb06420ee6a0399991fd97b2dec912872990a5a2 /eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks | |
download | National_eIDAS_Gateway-ae550884f5467f6ff6df23100686bc54e100d2d4.tar.gz National_eIDAS_Gateway-ae550884f5467f6ff6df23100686bc54e100d2d4.tar.bz2 National_eIDAS_Gateway-ae550884f5467f6ff6df23100686bc54e100d2d4.zip |
initial commit
Diffstat (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks')
3 files changed, 616 insertions, 0 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 new file mode 100644 index 00000000..dfd945c9 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java @@ -0,0 +1,160 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks; + +import java.io.InputStream; +import java.text.SimpleDateFormat; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.joda.time.DateTime; +import org.springframework.stereotype.Component; +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; + +/** + * @author tlenz + * + */ +@Component("CreateIdentityLinkTask") +public class CreateIdentityLinkTask 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) + */ + @Override + public void execute(ExecutionContext executionContext, + 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; + + //connect SZR-Gateway + //TODO: implement SZR-Gateway communication!!!! + if(true) { + + // 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(); + + // 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); + + //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); + + // - 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); + + // - 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()); + prDateOfBirth.getFirstChild().setNodeValue(formatedDateOfBirth); + + identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink(); + + //resign IDL + IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance(); + Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), authConfig.getStorkFakeIdLResigningKey()); + identityLink = new IdentityLinkAssertionParser(resignedilAssertion).parseIdentityLink(); + + } else { + //contact SZR Gateway + Logger.debug("Starting connecting SZR Gateway"); + + //TODO:!!!!!! + + } + + Logger.debug("SZR communication was successfull"); + + 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 + requestStoreage.storePendingRequest(pendingReq); + + } catch (eIDASAttributeException e) { + throw new TaskExecutionException(pendingReq, "Minimum required eIDAS attributeset not found.", e); + + } catch (MOAIDException | MOADatabaseException e) { + throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); + + } catch (Exception e) { + Logger.error("IdentityLink generation for foreign person FAILED.", e); + throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); + + } + } + +} 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 new file mode 100644 index 00000000..358b681e --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java @@ -0,0 +1,313 @@ +/******************************************************************************* + *******************************************************************************/ +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.UUID; + +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.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import com.google.common.net.MediaType; + +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 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.protocol.eidas.SpType; +import eu.eidas.auth.commons.protocol.eidas.impl.EidasAuthenticationRequest; + +/** + * @author tlenz + * + */ +@Component("GenerateAuthnRequestTask") +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) + */ + @Override + public void execute(ExecutionContext executionContext, + HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + + try{ + //get service-provider configuration + IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration(); + + // get target and validate citizen countryCode + String citizenCountryCode = (String) executionContext.get(MOAIDAuthConstants.PARAM_CCC); + + if (StringUtils.isEmpty(citizenCountryCode)) { + // illegal state; task should not have been executed without a selected country + throw new AuthenticationException("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: switch to entityID and set new status codes +// 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(); + + 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); + + //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); + + + //set correct SPType for this online application + if (oaConfig.hasBaseIdTransferRestriction()) + authnRequestBuilder.spType(SpType.PRIVATE.getValue()); + else + authnRequestBuilder.spType(SpType.PUBLIC.getValue()); + + + //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(); + + + + //IRequestMessage authnRequest = engine.generateRequestMessage(authnRequestBuilder.build(), issur); + + //encode AuthnRequest +// byte[] token = authnRequest.getMessageBytes(); +// String SAMLRequest = EidasStringUtil.encodeToBase64(token); + + +// 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"}); +// +// } + + + +// }catch (EIDASSAMLEngineException e){ +// throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.", +// new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e)); + + } catch (MOAIDException e) { + throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.", e); + + } catch (Exception e) { + Logger.error("eIDAS AuthnRequest generation FAILED.", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + } + + /** + * 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 + 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); + + 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()); + + + 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); + + } + + } + + /** + * 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; + } + +} 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 new file mode 100644 index 00000000..055c402f --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java @@ -0,0 +1,143 @@ +/******************************************************************************* + *******************************************************************************/ +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.springframework.beans.factory.annotation.Autowired; +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; + +@Component("ReceiveAuthnResponseTask") +public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { + + @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider; + + @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); + + } + + //get MOASession + defaultTaskInitialization(request, executionContext); + + //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()}); + + } + + // ********************************************************** + // ******* MOA-ID specific response validation ********** + // ********************************************************** + String spCountry = authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT"); + eIDASResponseValidator.validateResponse(pendingReq, samlResp, spCountry); + + + // ********************************************************** + // ******* Store resonse infos into session object ********** + // ********************************************************** + + //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); + + //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()); + + } catch (MOAIDException 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); + throw new TaskExecutionException(pendingReq, e.getMessage(), + new MOAIDException("eIDAS.10", new Object[]{e.getMessage()}, e)); + + } + + } + +} |