/******************************************************************************* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. ******************************************************************************/ /** * */ package at.gv.egovernment.moa.id.auth.stork; import java.io.ByteArrayInputStream; import java.util.List; import java.util.Vector; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.namespace.QName; import org.opensaml.common.binding.BasicSAMLMessageContext; import org.opensaml.saml2.binding.decoding.HTTPPostDecoder; import org.opensaml.saml2.core.Assertion; import org.opensaml.saml2.metadata.RequestedAttribute; import org.opensaml.ws.transport.http.HTTPInTransport; import org.opensaml.ws.transport.http.HTTPOutTransport; import org.opensaml.ws.transport.http.HttpServletRequestAdapter; import org.opensaml.ws.transport.http.HttpServletResponseAdapter; import org.opensaml.xml.XMLObject; import org.opensaml.xml.schema.XSAny; import org.opensaml.xml.schema.XSString; import org.opensaml.xml.util.Base64; import org.opensaml.xml.util.XMLHelper; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import at.gv.egovernment.moa.id.auth.AuthenticationServer; import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute; import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttributeImpl; import at.gv.egovernment.moa.id.auth.data.IdentityLink; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.exception.ParseException; import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; import at.gv.egovernment.moa.id.client.SZRGWClientException; import at.gv.egovernment.moa.id.util.XMLUtil; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Constants; import at.gv.egovernment.moa.util.DateTimeUtils; import at.gv.egovernment.moa.util.StringUtils; import at.gv.util.xsd.srzgw.CreateIdentityLinkResponse; import eu.stork.peps.auth.commons.IPersonalAttributeList; import eu.stork.peps.auth.commons.PersonalAttribute; /** * * Handles all functionality for the processing of a STORK response * @author bzwattendorfer * */ public class STORKResponseProcessor { /** OASIS DSS Namespace */ public static final String OASIS_DSS_NS = "urn:oasis:names:tc:dss:1.0:core:schema"; /** OASIS DSS Success Message */ public static final String OASIS_DSS_SUCCESS_MSG = "urn:oasis:names:tc:dss:1.0:resultmajor:Success"; /** * Checks for attribute. * * @param attributeName the attribute name * @param attributeList the attribute list * @return true, if successful */ public static boolean hasAttribute(String attributeName, IPersonalAttributeList attributeList) { try { getAttributeValue(attributeName, attributeList); return true; } catch(STORKException e) { return false; } } /** * helper for reading attributes. Handles logging and error handling. * * @param attributeName the attribute name * @param attributeList the attribute list * @return the attribute value * @throws STORKException the sTORK exception */ private static String getAttributeValue(String attributeName, IPersonalAttributeList attributeList) throws STORKException { try { String result = attributeList.get(attributeName).getValue().get(0); Logger.trace(attributeName + " : " + result); return result; } catch(NullPointerException e) { Logger.error(attributeName + " not found in response"); throw new STORKException(attributeName + " not found in response"); } } /** * Handels connection to SZR-GW and returns Identity Link on success. * * @param attributeList the attribute list * @param oaFriendlyName the oa friendly name * @param targetType the target type * @param targetValue the target value * @param filters the filters * @return Identity Link * @throws STORKException the sTORK exception * @throws MOAIDException */ public static IdentityLink connectToSZRGateway(IPersonalAttributeList attributeList, String oaFriendlyName, String targetType, String targetValue, List filters) throws STORKException, MOAIDException { Logger.trace("Calling SZR Gateway with the following attributes:"); CreateIdentityLinkResponse identityLinkResponse = null; IdentityLink identityLink = null; try { Logger.trace("Starting call..."); // if there is no signedDoc attribute, we cannot go on String fiscalNumber = null; String citizenSignature = getAttributeValue("signedDoc", attributeList); if (hasAttribute("fiscalNumber", attributeList)) fiscalNumber = getAttributeValue("fiscalNumber", attributeList); // if we have a signedDoc we test for a representation case // - according to stork samlengine and commons if(hasAttribute("mandate", attributeList)) { // we have a representation case String mandate = getAttributeValue("mandate", attributeList); if(!hasAttribute("dateOfBirth", attributeList)) { // if we get here, we have a natural person representing a legal person String organizationAddress = getAttributeValue("canonicalRegisteredAddress", attributeList); String organizationType = getAttributeValue("translateableType", attributeList); identityLinkResponse = AuthenticationServer.getInstance().getIdentityLink(citizenSignature, null, null, mandate, organizationAddress, organizationType, targetType, targetValue, oaFriendlyName, filters, fiscalNumber); } else { // if we get here, we have a natural person representing another natural person String eIdentifier = getAttributeValue("eIdentifier", attributeList); String givenName = getAttributeValue("givenName", attributeList); String lastName = getAttributeValue("surname", attributeList); String dateOfBirth = null; if (hasAttribute("dateOfBirth", attributeList)) { dateOfBirth = getAttributeValue("dateOfBirth", attributeList); dateOfBirth = DateTimeUtils.formatPEPSDateToMOADate(dateOfBirth); } // gender attribute is mandatory here because of some legal stuff String gender = getAttributeValue("gender", attributeList); identityLinkResponse = AuthenticationServer.getInstance().getIdentityLink(eIdentifier, givenName, lastName, dateOfBirth, gender, citizenSignature, null, null, mandate, targetType, targetValue, oaFriendlyName, filters, fiscalNumber); } } // - according to stork spec else if(hasAttribute("mandateContent", attributeList) || hasAttribute("representative", attributeList) || hasAttribute("represented", attributeList)) { // we have a representation case String representative = getAttributeValue("representative", attributeList); String represented = getAttributeValue("represented", attributeList); String mandate = getAttributeValue("mandateContent", attributeList); if(!hasAttribute("dateOfBirth", attributeList)) { // if we get here, we have a natural person representing a legal person String organizationAddress = getAttributeValue("canonicalRegisteredAddress", attributeList); String organizationType = getAttributeValue("translateableType", attributeList); identityLinkResponse = AuthenticationServer.getInstance().getIdentityLink(citizenSignature, representative, represented, mandate, organizationAddress, organizationType, targetType, targetValue, oaFriendlyName, filters, fiscalNumber); } else { // if we get here, we have a natural person representing another natural person String eIdentifier = getAttributeValue("eIdentifier", attributeList); String givenName = getAttributeValue("givenName", attributeList); String lastName = getAttributeValue("surname", attributeList); String dateOfBirth = null; if (hasAttribute("dateOfBirth", attributeList)) { dateOfBirth = getAttributeValue("dateOfBirth", attributeList); dateOfBirth = DateTimeUtils.formatPEPSDateToMOADate(dateOfBirth); } // gender attribute is mandatory here because of some legal stuff String gender = getAttributeValue("gender", attributeList); identityLinkResponse = AuthenticationServer.getInstance().getIdentityLink(eIdentifier, givenName, lastName, dateOfBirth, gender, citizenSignature, representative, represented, mandate, targetType, targetValue, oaFriendlyName, filters, fiscalNumber); } } else { // we do not have a representation case String eIdentifier = getAttributeValue("eIdentifier", attributeList); String givenName = getAttributeValue("givenName", attributeList); String lastName = getAttributeValue("surname", attributeList); String dateOfBirth = null; if (hasAttribute("dateOfBirth", attributeList)) { dateOfBirth = getAttributeValue("dateOfBirth", attributeList); dateOfBirth = DateTimeUtils.formatPEPSDateToMOADate(dateOfBirth); } identityLinkResponse = AuthenticationServer.getInstance().getIdentityLink(eIdentifier, givenName, lastName, dateOfBirth, citizenSignature, fiscalNumber); } if (null != identityLinkResponse.getErrorResponse()){ throw new SZRGWClientException("service.08", (String)identityLinkResponse.getErrorResponse().getErrorCode(), (String)identityLinkResponse.getErrorResponse().getInfo()); } else { IdentityLinkAssertionParser ilParser = new IdentityLinkAssertionParser(new ByteArrayInputStream(identityLinkResponse.getIdentityLink())); identityLink = ilParser.parseIdentityLink(); Logger.debug("Received Identity Link from SZR Gateway"); //TODO: is this ok? // if (StringUtils.isEmpty(identityLink.getDateOfBirth())) { // identityLink.setDateOfBirth("9999-12-31"); // } } } catch (ParseException e) { Logger.error("Error parsing IdentityLink received from SZR-Gateway: ", e); throw new MOAIDException("auth.25", null, e); } return identityLink; } /** * Transforms additional STORK attributes to MOA Extended attributes * @param iPersonalAttributeList STORK attribute list * @return */ public static List addAdditionalSTORKAttributes(IPersonalAttributeList iPersonalAttributeList) { List moaExtendedSAMLAttributeList = new Vector(); if(null == iPersonalAttributeList) return moaExtendedSAMLAttributeList; Logger.trace("Adding the following attributes to MOA assertion: "); int count = 0; for (PersonalAttribute attribute : iPersonalAttributeList) { Object attributeValue = attribute.getValue(); if (null == attributeValue) attributeValue = attribute.getComplexValue(); ExtendedSAMLAttribute extendedSAMLAttribute = new ExtendedSAMLAttributeImpl(attribute.getName(), attributeValue, Constants.STORK_NS_URI, 0); moaExtendedSAMLAttributeList.add(extendedSAMLAttribute); count++; Logger.trace("Additional attribute: " + attribute.getName()); } Logger.debug("Added " + count + " STORK attribute(s) to the MOA assertion."); return moaExtendedSAMLAttributeList; } }