diff options
Diffstat (limited to 'id/server/idserverlib/src')
5 files changed, 1129 insertions, 0 deletions
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/AttributeProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/AttributeProvider.java new file mode 100644 index 000000000..682af2a5e --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/AttributeProvider.java @@ -0,0 +1,89 @@ +package at.gv.egovernment.moa.id.protocols.stork2.attributeproviders; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.protocols.stork2.ExternalAttributeRequestRequiredException; +import at.gv.egovernment.moa.id.protocols.stork2.UnsupportedAttributeException; +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PersonalAttribute; + +/** + * An {@link AttributeProvider} can fetch a set of stork attributes. It might complete the query within one method call, + * but might also need to redirect to another webservice to accomplish its task. + */ +public abstract class AttributeProvider { + + protected String attributes; + + public AttributeProvider(String attributes){ + this.attributes = attributes; + } + + /** + * Acquire the specified attribute. Returns {@code null} when attribute retrieval is in progress, but requires for + * for redirecting the user to an external service. Use {@link AttributeProvider#parse(HttpServletRequest)} to parse + * the response. + * + * @param attributes the list of attributes to be acquired + * @param spCountyCode the sp county code + * @param authData the moasession + * @return the personal attribute + * @throws UnsupportedAttributeException the unsupported attribute exception + * @throws ExternalAttributeRequestRequiredException an attribute request to an external service has to be done + * @throws MOAIDException the mOAID exception + */ + protected abstract IPersonalAttributeList acquire(PersonalAttribute attributes, String spCountyCode, IAuthData authData) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException, MOAIDException; + + public IPersonalAttributeList acquire(List<PersonalAttribute> attributes, String spCountyCode, IAuthData authData) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException, MOAIDException { + if (attributes.size() == 1) { + return acquire(attributes.get(0), spCountyCode, authData); + } else { + throw new MOAIDException("stork.13", new Object[] { }); // TODO message only one attribute supported by this provider + + } + } + + /** + * Perform redirect. + * + * @param url the return URL ending with ?artifactId=... + * @param req the request we got from the S-PEPS and for which we have to ask our APs + * @param resp the response to the preceding request + * @param oaParam the oa param + * @throws MOAIDException the mOAID exception + */ + public abstract void performRedirect(String url, HttpServletRequest req, HttpServletResponse resp, OAAuthParameter oaParam) throws MOAIDException; + + /** + * Parses the response we got from the external attribute provider. + * + * @param httpReq the http req + * @return a list of attributes + * @throws UnsupportedAttributeException if the provider cannot find anything familiar in the provided httpReq + * @throws MOAIDException if something went wrong + */ + public abstract IPersonalAttributeList parse(HttpServletRequest httpReq) throws UnsupportedAttributeException, MOAIDException; + + /** + * Returns the list of supported attributes + * + * @return a list of attributes + * @throws MOAIDException if something went wrong + */ + public List<String> getSupportedAttributeNames() throws MOAIDException { + ArrayList<String> supportedAttributeNames = new ArrayList<String>(); + for (String attributeName : this.attributes.split(",")) { + supportedAttributeNames.add(attributeName); + } + return supportedAttributeNames; + } + + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/EHvdAttributeProviderPlugin.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/EHvdAttributeProviderPlugin.java new file mode 100644 index 000000000..91cc86ca9 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/EHvdAttributeProviderPlugin.java @@ -0,0 +1,227 @@ +package at.gv.egovernment.moa.id.protocols.stork2.attributeproviders; + +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.soap.MessageFactory; +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPConnection; +import javax.xml.soap.SOAPConnectionFactory; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.SOAPEnvelope; +import javax.xml.soap.SOAPMessage; +import javax.xml.soap.SOAPPart; + +import at.gv.egovernment.moa.id.auth.builder.BPKBuilder; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.protocols.stork2.ExternalAttributeRequestRequiredException; +import at.gv.egovernment.moa.id.protocols.stork2.UnsupportedAttributeException; +import at.gv.egovernment.moa.logging.Logger; +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PersonalAttribute; +import eu.stork.peps.auth.commons.PersonalAttributeList; +import eu.stork.peps.complex.attributes.IsHealthCareProfessionalType; +import eu.stork.peps.complex.attributes.ObjectFactory; + +/** + * Fetches the attribute IsHealthcareProfessional from the BAGDAD SOAP service + */ +public class EHvdAttributeProviderPlugin extends AttributeProvider { + + /** The destination. */ + private Object destination; + + /** + * Instantiates a new e hvd attribute provider plugin. + * + * @param url the service url + * @param attributes + */ + public EHvdAttributeProviderPlugin(String url, String supportedAttributes) { + super(supportedAttributes); + destination = url; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#acquire(eu.stork.peps.auth.commons.PersonalAttribute) + */ + @Override + protected IPersonalAttributeList acquire(PersonalAttribute attribute, String spCountryCode, IAuthData authData) + throws UnsupportedAttributeException, + ExternalAttributeRequestRequiredException, MOAIDException { + + // break when we cannot handle the requested attribute + if(!attributes.contains(attribute.getName())) + throw new UnsupportedAttributeException(); + + try { + Logger.debug("initializing SOAP connections..."); + // create SOAP connection + SOAPConnection soapConnection = SOAPConnectionFactory.newInstance().createConnection(); + + // assemble SOAP request + MessageFactory messageFactory = MessageFactory.newInstance(); + SOAPMessage requestMessage = messageFactory.createMessage(); + SOAPPart requestPart = requestMessage.getSOAPPart(); + + // (soap 1.1 relevant part. could not find a solution to use soap 1.2 in time. + requestMessage.getMimeHeaders().setHeader("SOAPAction", "http://gesundheit.gv.at/BAGDAD/DataAccessService/IsHealthcareProfessional"); + + /* + Construct SOAP Request Message: + <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> + <soap:Body> + <IsHealthcareProfessional xmlns="http://gesundheit.gv.at/BAGDAD/DataAccessService"> + <bPK>string</bPK> + </IsHealthcareProfessional> + </soap:Body> + </soap:Envelope> + + see https://stork.ehealth.gv.at/GDAService.asmx?op=IsHealthcareProfessional + */ + + // SOAP Envelope + SOAPEnvelope envelope = requestPart.getEnvelope(); + + // SOAP Body + SOAPBody requestBody = envelope.getBody(); + SOAPElement requestBodyElem = requestBody.addChildElement("IsHealthcareProfessional"); + requestBodyElem.addAttribute(envelope.createName("xmlns"), "http://gesundheit.gv.at/BAGDAD/DataAccessService"); + + SOAPElement requestBodyElem1 = requestBodyElem.addChildElement("bPK"); + + //TODO: CHECK: IdentificationValue containts wbPK if MOA-ID is used as VIDP + requestBodyElem1.addTextNode(new BPKBuilder().buildBPK(authData.getIdentificationValue(), "GH")); + + requestMessage.saveChanges(); + + // perform SOAP call + Logger.debug("call..."); + SOAPMessage responseMessage = soapConnection.call(requestMessage, destination); + + // parse SOAP response + + /* + <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> + <soap:Body> + <IsHealthcareProfessionalResponse xmlns="http://gesundheit.gv.at/BAGDAD/DataAccessService"> + <IsHealthcareProfessionalResult> + <RequestOK>boolean</RequestOK> + <Message>string</Message> + <IsHealthcareProfessional>boolean</IsHealthcareProfessional> + <NameOfOrganisation>string</NameOfOrganisation> + <Type>string</Type> + <Specialization>string</Specialization> + </IsHealthcareProfessionalResult> + </IsHealthcareProfessionalResponse> + </soap:Body> + </soap:Envelope> + + see https://stork.ehealth.gv.at/GDAService.asmx?op=IsHealthcareProfessional + */ + Logger.debug("call successful. Parse..."); + SOAPBody responseBody = responseMessage.getSOAPBody(); + + // iterate through tree + SOAPElement responseElement = (SOAPElement) responseBody.getChildElements().next(); + SOAPElement resultElement = (SOAPElement) responseElement.getChildElements().next(); + + // collect all info in a map + Iterator<?> it = resultElement.getChildElements(); + Map<String, String> collection = new HashMap<String, String>(); + while (it.hasNext()) { + SOAPElement current = (SOAPElement) it.next(); + + collection.put(current.getNodeName(), current.getTextContent()); + } + + // check if there is anything valid in the map + if (collection.isEmpty() || collection.size() != 6) { + Logger.warn("eHVD returned an unexpected count of values. Expected 6 got " + collection.size()); + throw new IndexOutOfBoundsException("response attributes not like specified"); + } + + // - fetch request validity + if (collection.get("RequestOK").equals("false")) { + Logger.warn("eHVD reported an invalid request. The error message is: " + collection.get("Message")); + throw new Exception("eHVD reported an invalid request"); + } + + PersonalAttribute acquiredAttribute = null; + + if (collection.get("IsHealthcareProfessional").equals("false")) { + // the citizen is no HCP + acquiredAttribute = new PersonalAttribute("isHealthCareProfessional", false, new ArrayList<String>(), "NotAvailable"); + } else { + // go on and parse the data + IsHealthCareProfessionalType result = new IsHealthCareProfessionalType(); + result.setNameOfOrganisation(collection.get("NameOfOrganisation")); + + if (collection.get("Type").equals("Medical doctor")) + result.setHCPType("D"); + else + result.setHCPType("?"); + + if (collection.get("Specialization").contains("Arzt für Allgemeinmedizin")) + result.setSpecialisation("GP"); + else + result.setSpecialisation("??"); + + result.setAQAA(4); + + final Marshaller m = JAXBContext.newInstance(IsHealthCareProfessionalType.class).createMarshaller(); + m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + + StringWriter stringWriter = new StringWriter(); + m.marshal(new ObjectFactory().createIsHealthCareProfessional(result), stringWriter); + + ArrayList<String> value = new ArrayList<String>(); + value.add(stringWriter.toString()); + + acquiredAttribute = new PersonalAttribute("isHealthCareProfessional", false, value, "Available"); + } + + // pack and return the result + PersonalAttributeList result = new PersonalAttributeList(); + result.add(acquiredAttribute); + + // add stork id for verification + ArrayList<String> value = new ArrayList<String>(); + value.add(new BPKBuilder().buildStorkeIdentifier(authData.getIdentityLink(), spCountryCode)); + result.add(new PersonalAttribute("eIdentifier", false, value, "Available")); + + return result; + } catch (Exception e) { + throw new MOAIDException("stork.13", new Object[] { e }); + } + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#performRedirect(java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.config.auth.OAAuthParameter) + */ + public void performRedirect(String url, + HttpServletRequest req, HttpServletResponse resp, + OAAuthParameter oaParam) throws MOAIDException { + // there is no redirect required + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#parse(javax.servlet.http.HttpServletRequest) + */ + public IPersonalAttributeList parse(HttpServletRequest httpReq) + throws UnsupportedAttributeException, MOAIDException { + // there is no redirect required, so we throw an exception when someone asks us to parse a response + throw new UnsupportedAttributeException(); + } + + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java new file mode 100644 index 000000000..49250df6b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java @@ -0,0 +1,159 @@ +package at.gv.egovernment.moa.id.protocols.stork2.attributeproviders; + +import java.io.StringWriter; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; + +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.protocols.stork2.ExternalAttributeRequestRequiredException; +import at.gv.egovernment.moa.id.protocols.stork2.UnsupportedAttributeException; +import at.gv.egovernment.moa.id.util.HTTPUtils; +import at.gv.egovernment.moa.id.util.VelocityProvider; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.StringUtils; +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PEPSUtil; +import eu.stork.peps.auth.commons.PersonalAttribute; +import eu.stork.peps.auth.commons.PersonalAttributeList; +import eu.stork.peps.auth.commons.STORKAttrQueryRequest; +import eu.stork.peps.auth.engine.STORKSAMLEngine; +import eu.stork.peps.exceptions.STORKSAMLEngineException; + +/** + * Provides mandate attribute from MIS + */ +public class MandateAttributeRequestProvider extends AttributeProvider { + /** + * The destination. + */ + private String destination; + + private String spCountryCode; + + private PersonalAttributeList requestedAttributes; + + public MandateAttributeRequestProvider(String aPurl, String supportedAttributes) throws MOAIDException { + super(supportedAttributes); + destination = aPurl; + + } + + public String getAttrProviderName() { + return "MandateAttributeRequestProvider"; + } + + @Override + protected IPersonalAttributeList acquire(PersonalAttribute attribute, String spCountryCode, IAuthData authData) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException, MOAIDException { + Logger.info("Acquiring attribute: " + attribute.getName() + ", by: " + getAttrProviderName()); + this.spCountryCode = spCountryCode; + requestedAttributes = new PersonalAttributeList(1); + requestedAttributes.add(attribute); + + // break if we cannot handle the requested attribute + if (!attributes.contains(attribute.getName())) { + Logger.info("Attribute " + attribute.getName() + " not supported by the provider: " + getAttrProviderName()); + throw new UnsupportedAttributeException(); + } + PersonalAttributeList result = new PersonalAttributeList(); + //return result; + + + + Logger.info("Thrown external request by: " + getAttrProviderName()); + throw new ExternalAttributeRequestRequiredException(this); + } + + @Override + public IPersonalAttributeList acquire(List<PersonalAttribute> attributes, String spCountryCode, IAuthData moasession) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException, MOAIDException { + Logger.info("Acquiring " + attributes.size() + " attributes, by: " + getAttrProviderName()); + this.spCountryCode = spCountryCode; + requestedAttributes = new PersonalAttributeList(attributes.size()); + + for (PersonalAttribute personalAttribute : attributes) { + // break if we cannot handle the requested attribute + if (!this.attributes.contains(personalAttribute.getName())) { + Logger.info("Attribute " + personalAttribute.getName() + " not supported by the provider: " + getAttrProviderName()); + throw new UnsupportedAttributeException(); + } + requestedAttributes.add(personalAttribute); + } + + Logger.info("Thrown external request by: " + getAttrProviderName()); + throw new ExternalAttributeRequestRequiredException(this); + } + + + + + public void performRedirect(String url, HttpServletRequest req, HttpServletResponse resp, OAAuthParameter oaParam) throws MOAIDException { + + String spSector = "Business"; + String spInstitution = StringUtils.isEmpty(oaParam.getFriendlyName()) ? "UNKNOWN" : oaParam.getFriendlyName(); + String spApplication = spInstitution; + + //generate AttrQueryRequest + STORKAttrQueryRequest attributeRequest = new STORKAttrQueryRequest(); + attributeRequest.setDestination(destination); + attributeRequest.setAssertionConsumerServiceURL(url); + attributeRequest.setIssuer(HTTPUtils.getBaseURL(req)); + attributeRequest.setQaa(oaParam.getQaaLevel()); + attributeRequest.setSpInstitution(spInstitution); + attributeRequest.setCountry(spCountryCode); + attributeRequest.setSpCountry(spCountryCode); + attributeRequest.setSpApplication(spApplication); + attributeRequest.setSpSector(spSector); + attributeRequest.setPersonalAttributeList(requestedAttributes); + + attributeRequest.setCitizenCountryCode("AT"); + + + + + + Logger.info("STORK AttrRequest successfully assembled."); + + STORKSAMLEngine samlEngine = STORKSAMLEngine.getInstance("VIDP"); + try { + attributeRequest = samlEngine.generateSTORKAttrQueryRequest(attributeRequest); + } catch (STORKSAMLEngineException e) { + Logger.error("Could not sign STORK SAML AttrRequest.", e); + throw new MOAIDException("stork.00", null); + } + + Logger.info("STORK AttrRequest successfully signed!"); + + try { + Logger.trace("Initialize VelocityEngine..."); + + VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); + Template template = velocityEngine.getTemplate("/resources/templates/saml2-post-binding-moa.vm"); + VelocityContext context = new VelocityContext(); + context.put("SAMLRequest", PEPSUtil.encodeSAMLToken(attributeRequest.getTokenSaml())); + context.put("action", destination); + + StringWriter writer = new StringWriter(); + template.merge(context, writer); + + resp.getOutputStream().write(writer.toString().getBytes()); + } catch (Exception e) { + Logger.error("Error sending STORK SAML AttrRequest.", e); + throw new MOAIDException("stork.11", null); + } + Logger.info("STORK AttrRequest successfully rendered!"); + + } + + public IPersonalAttributeList parse(HttpServletRequest httpReq) throws UnsupportedAttributeException, MOAIDException { + return null; // + } + +} + diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java new file mode 100644 index 000000000..3256e1812 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java @@ -0,0 +1,492 @@ +package at.gv.egovernment.moa.id.protocols.stork2.attributeproviders; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.activation.DataSource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.stream.StreamSource; +import javax.xml.ws.Service; +import javax.xml.ws.soap.SOAPBinding; +import javax.xml.ws.BindingProvider; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.NotImplementedException; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; + +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.protocols.stork2.ExternalAttributeRequestRequiredException; +import at.gv.egovernment.moa.id.protocols.stork2.UnsupportedAttributeException; +import at.gv.egovernment.moa.id.util.VelocityProvider; +import at.gv.egovernment.moa.logging.Logger; +import eu.stork.oasisdss.api.ApiUtils; +import eu.stork.oasisdss.api.LightweightSourceResolver; +import eu.stork.oasisdss.api.exceptions.ApiUtilsException; +import eu.stork.oasisdss.api.exceptions.UtilsException; +import eu.stork.oasisdss.profile.Base64Data; +import eu.stork.oasisdss.profile.DocumentType; +import eu.stork.oasisdss.profile.IncludeObject; +import eu.stork.oasisdss.profile.SignRequest; +import eu.stork.oasisdss.profile.SignResponse; +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PEPSUtil; +import eu.stork.peps.auth.commons.PersonalAttribute; +import eu.stork.peps.auth.commons.PersonalAttributeList; +import eu.stork.peps.auth.commons.STORKAttrQueryRequest; +import eu.stork.peps.auth.engine.STORKSAMLEngine; +import eu.stork.peps.exceptions.STORKSAMLEngineException; +import eu.stork.documentservice.DocumentService; +/** + * Forwards a signedDoc attribute request to the oasis-dss service instance + */ +public class SignedDocAttributeRequestProvider extends AttributeProvider { + + private String dtlUrl = null; + private PersonalAttribute requestedAttribute; + + /** + * The URL of the service listening for the oasis dss webform post request + */ + private String oasisDssWebFormURL; + + /** + * Instantiates a new signed doc attribute request provider. + * + * @param oasisDssWebFormURL + * the AP location + * @param attributes + */ + public SignedDocAttributeRequestProvider(String oasisDssWebFormURL, String attributes) { + super(attributes); + this.oasisDssWebFormURL = oasisDssWebFormURL; + //TODO load dtlUrl from config + dtlUrl = "http://mopsos.iaik.tugraz.at:8080/DocumentService/DocumentService"; + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#acquire(java + * .lang.String) + */ + @Override + protected IPersonalAttributeList acquire(PersonalAttribute attribute, String spCountyCode, IAuthData authData) throws UnsupportedAttributeException, + ExternalAttributeRequestRequiredException { + if(!attributes.contains(attribute.getName())) { + throw new UnsupportedAttributeException(); + } + + requestedAttribute = attribute; + + throw new ExternalAttributeRequestRequiredException(this); + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#parse(javax + * .servlet.http.HttpServletRequest) + */ + public IPersonalAttributeList parse(HttpServletRequest httpReq) throws MOAIDException, UnsupportedAttributeException { + Logger.debug("Beginning to extract OASIS-DSS response out of HTTP Request"); + + try { + String signResponseString = new String(Base64.decodeBase64(httpReq.getParameter("signresponse")), "UTF8"); + //TODO + //FIXME + //test123 + //create SignResponse object + Source response = new StreamSource(new java.io.StringReader(signResponseString)); + SignResponse signResponse = ApiUtils.unmarshal(response, SignResponse.class); + //extract doc from signresponse + DataSource dataSource = LightweightSourceResolver.getDataSource(signResponse); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + IOUtils.copy(dataSource.getInputStream(), baos); + byte[] data = baos.toByteArray(); + + //update doc in DTL + String docId, dssId = ""; + docId = signResponse.getDocUI(); + //For reference dssId equals docId + dssId = docId; + if (dssId != null && data!=null) + { + if(updateDocumentInDtl(data, docId, signResponseString)) + { +// SignResponse outRes = new SignResponse(); +// outRes.setDocUI(signResponse.getDocUI()); +// outRes.setProfile(signResponse.getProfile()); +// outRes.setRequestID(signResponse.getRequestID()); +// outRes.setSignatureObject(signResponse.getSignatureObject()); + //outRes; + + signResponse.getResult().setResultMinor(dtlUrl); + System.out.println("overwriting:"+signResponse.getResult().getResultMessage()+" with DTL url:"+dtlUrl); + InputStream istr = ApiUtils.marshalToInputStream(signResponse); + StringWriter writer = new StringWriter(); + IOUtils.copy(istr, writer, "UTF-8"); + signResponseString = writer.toString(); + System.out.println("SignResponse overwritten:"+signResponseString); + } + } + else + throw new Exception("No DSS id found."); + + + //alter signresponse + //done + List<String> values = new ArrayList<String>(); + values.add(signResponseString); + + Logger.debug("Assembling signedDoc attribute"); + PersonalAttribute signedDocAttribute = new PersonalAttribute("signedDoc", false, values, + "Available"); + + // pack and return the result + PersonalAttributeList result = new PersonalAttributeList(); + result.add(signedDocAttribute); + return result; + } catch (UnsupportedEncodingException e) { + Logger.error("Failed to assemble signedDoc attribute"); + throw new MOAIDException("stork.05", null); + } catch (ApiUtilsException e) { + e.printStackTrace(); + Logger.error("Failed to assemble signedDoc attribute"); + throw new MOAIDException("stork.05", null); + } catch (IOException e) { + e.printStackTrace(); + Logger.error("Failed to assemble signedDoc attribute"); + throw new MOAIDException("stork.05", null); + } catch (Exception e) { + e.printStackTrace(); + Logger.error("Failed to assemble signedDoc attribute"); + throw new MOAIDException("stork.05", null); + } + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#performRedirect + * (java.lang.String) + */ + public void performRedirect(String url, HttpServletRequest req, HttpServletResponse resp, OAAuthParameter oaParam) + throws MOAIDException { + + try { + Logger.trace("Initialize VelocityEngine..."); + + VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); + Template template = velocityEngine.getTemplate("/resources/templates/oasis_dss_webform_binding.vm"); + VelocityContext context = new VelocityContext(); + + //Parse SignRequest + String signRequestString = requestedAttribute.getValue().get(0); + Source signDoc = new StreamSource(new java.io.StringReader(signRequestString)); + SignRequest signRequest = ApiUtils.unmarshal(signDoc, SignRequest.class); + try{ + //TODO + //FIXME + //search for DTL link + String dtlURL = getDtlUrlFromRequest(signRequest); + String docId = signRequest.getDocUI(); + + String docRequest = getDocTransferRequest(docId, dtlURL);//dtlUrl + + byte[] data = getDocumentFromDtl(docRequest, dtlURL);//dtlUrl + //load doc from DTL + System.out.println("data:"+data); + String mime = getDocumentMimeFromDtl(docId, dtlURL);//dtlUrl + System.out.println("mime:"+mime); + //add doc as base64* to signrequest => post doc to oasis + try{ + List<IncludeObject> includeObjects = ApiUtils.findNamedElement( + signRequest.getOptionalInputs(), "IncludeObject", + IncludeObject.class); + signRequest.getOptionalInputs().getAny().removeAll(includeObjects); + + DocumentType document = new DocumentType(); + Base64Data b64data = new Base64Data(); + b64data.setValue(data); + b64data.setMimeType(mime); + document.setBase64Data(b64data); + signRequest.setInputDocuments(ApiUtils.createInputDocuments(document)); + //override old signRequestString + + InputStream istr = ApiUtils.marshalToInputStream(signRequest); + StringWriter writer = new StringWriter(); + IOUtils.copy(istr, writer, "UTF-8"); + signRequestString = writer.toString(); + System.out.println("Signrequest overwritten"); + } catch (Exception e) { + e.printStackTrace(); + throw new Exception("Could not marshall sign request", e); + } + + + }catch(Exception e) + { + Logger.info("No documentservice used?"); + e.printStackTrace(); + } + + context.put("signrequest", Base64.encodeBase64String(signRequestString.getBytes("UTF8"))); + context.put("clienturl", url); + context.put("action", oasisDssWebFormURL); + + StringWriter writer = new StringWriter(); + template.merge(context, writer); + + resp.getOutputStream().write(writer.toString().getBytes()); + } catch (Exception e) { + Logger.error("Error sending DSS signrequest.", e); + throw new MOAIDException("stork.11", null); + } + } + + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#getSupportedAttributeNames() + */ + @Override + public List<String> getSupportedAttributeNames() throws MOAIDException { + ArrayList<String> supportedAttributeNames = new ArrayList<String>(); + for (String attributeName : this.attributes.split(",")) { + supportedAttributeNames.add(attributeName); + } + return supportedAttributeNames; + } + + + //From DTLPEPSUTIL + + /** + * Get DTL uril from the oasis sign request + * @param signRequest The signature request + * @return The URL of DTL service + * @throws SimpleException + */ + private String getDtlUrlFromRequest(SignRequest signRequest) throws Exception + { + if (signRequest == null) + throw new Exception("Signature request is empty"); + else + { + try + { + Object objDoc = signRequest.getInputDocuments().getDocumentOrTransformedDataOrDocumentHash().get(0); + if (objDoc instanceof DocumentType) + { + DocumentType document = (DocumentType)objDoc; + if (document.getDocumentURL() != null) + return document.getDocumentURL(); + else + throw new Exception("No document url found"); + } + else + throw new Exception("No input document found"); + } + catch (Exception ex) + { + throw new Exception("Unable to parse xml.", ex); + } + } + } + + /** + * Get document from DTL + * @param transferRequest The transfer request (attribute query) + * @param eDtlUrl The DTL url of external DTL + * @return the document data + * @throws SimpleException + */ + private byte[] getDocumentFromDtl(String transferRequest, String eDtlUrl) throws Exception + { + URL url = null; + try + { + url = new URL(dtlUrl); + QName qname = new QName("http://stork.eu", + "DocumentService"); + + Service service = Service.create(url, qname); + DocumentService docservice = service.getPort(DocumentService.class); + + BindingProvider bp = (BindingProvider) docservice; + SOAPBinding binding = (SOAPBinding) bp.getBinding(); + binding.setMTOMEnabled(true); + + if (eDtlUrl.equalsIgnoreCase(dtlUrl)) + return docservice.getDocument(transferRequest, ""); + else + return docservice.getDocument(transferRequest, eDtlUrl); + } + catch (Exception e) + { + e.printStackTrace(); + throw new Exception("Error in getDocumentFromDtl", e); + } + } + + /** + * Get a document transfer request (attribute query) + * @param docId + * @return + * @throws SimpleException + */ + private String getDocTransferRequest(String docId, String destinationUrl) throws Exception + { + final STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");//getInstance(samlDTLInstance); + STORKAttrQueryRequest req = new STORKAttrQueryRequest(); + req.setAssertionConsumerServiceURL(dtlUrl); + req.setDestination(destinationUrl); + req.setSpCountry("IS");//FIXME + req.setQaa(3);//TODO + PersonalAttributeList pal = new PersonalAttributeList(); + PersonalAttribute attr = new PersonalAttribute(); + attr.setName("docRequest"); + attr.setIsRequired(true); + attr.setValue(Arrays.asList(docId)); + pal.add(attr); + req.setPersonalAttributeList(pal); + + STORKAttrQueryRequest req1; + try { + req1 = engine.generateSTORKAttrQueryRequest(req); + return PEPSUtil.encodeSAMLTokenUrlSafe(req1.getTokenSaml()); + } catch (STORKSAMLEngineException e) { + e.printStackTrace(); + throw new Exception("Error in doc request attribute query generation", e); + } + } + + /** + * Get mime type of document from DTL + * @param docId The document id + * @param dtlUrl The url of dtl + * @return The mime type + */ + private String getDocumentMimeFromDtl(String docId, String eDtlUrl) throws Exception + { + URL url = null; + try + { + url = new URL(dtlUrl); + QName qname = new QName("http://stork.eu", + "DocumentService"); + + Service service = Service.create(url, qname); + DocumentService docservice = service.getPort(DocumentService.class); + + BindingProvider bp = (BindingProvider) docservice; + SOAPBinding binding = (SOAPBinding) bp.getBinding(); + binding.setMTOMEnabled(true); + + if (eDtlUrl.equalsIgnoreCase(dtlUrl)) + return docservice.getDocumentMime(docId, ""); + else + return docservice.getDocumentMime(docId, eDtlUrl); + } + catch (Exception e) + { + e.printStackTrace(); + throw new Exception("Error in getDocumentFromDtl", e); + } + } + + /** + * Add document to DTL service + * @param docData the document data + * @param mime the mime type of data + * @param signRequest the sign request + * @return the document id + * @throws SimpleException + */ + private String addDocumentToDtl(byte[] docData, String mime, String signRequest, String destCountry, String spId) throws Exception + { + throw new NotImplementedException(); +// URL url = null; +// String docID = null; +// try +// { +// url = new URL(dtlUrl); +// QName qname = new QName("http://stork.eu", +// "DocumentService"); +// +// Service service = Service.create(url, qname); +// DocumentService docservice = service.getPort(DocumentService.class); +// +// BindingProvider bp = (BindingProvider) docservice; +// SOAPBinding binding = (SOAPBinding) bp.getBinding(); +// binding.setMTOMEnabled(true); +// +// docID = docservice.addDocument(docData, signRequest, destCountry, spId, mime, ""); +// } +// catch (Exception e) +// { +// e.printStackTrace(); +// throw new Exception("Error in addDocumentToDtl", e); +// } +// +// return docID; + } + + /** + * Update document in DTL + * @param docData The docment data + * @param docId The document ID + * @param signResponse The signature response + * @return True if successful + * @throws SimpleException + */ + private boolean updateDocumentInDtl(byte[] docData, String docId, String signResponse) throws Exception + { + boolean success = false; + URL url = null; + try + { + url = new URL(dtlUrl); + QName qname = new QName("http://stork.eu", + "DocumentService"); + + Service service = Service.create(url, qname); + DocumentService docservice = service.getPort(DocumentService.class); + + BindingProvider bp = (BindingProvider) docservice; + SOAPBinding binding = (SOAPBinding) bp.getBinding(); + binding.setMTOMEnabled(true); + + success = docservice.updateDocument(docId, signResponse, docData); + } + catch (Exception e) + { + e.printStackTrace(); + throw new Exception("Error in addDocumentToDtl", e); + } + + return success; + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/StorkAttributeRequestProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/StorkAttributeRequestProvider.java new file mode 100644 index 000000000..4ec77e13d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/StorkAttributeRequestProvider.java @@ -0,0 +1,162 @@ +package at.gv.egovernment.moa.id.protocols.stork2.attributeproviders; + +import java.io.StringWriter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; + +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.protocols.stork2.ExternalAttributeRequestRequiredException; +import at.gv.egovernment.moa.id.protocols.stork2.UnsupportedAttributeException; +import at.gv.egovernment.moa.id.util.HTTPUtils; +import at.gv.egovernment.moa.id.util.VelocityProvider; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.StringUtils; +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PEPSUtil; +import eu.stork.peps.auth.commons.PersonalAttribute; +import eu.stork.peps.auth.commons.PersonalAttributeList; +import eu.stork.peps.auth.commons.STORKAttrQueryRequest; +import eu.stork.peps.auth.commons.STORKAttrQueryResponse; +import eu.stork.peps.auth.engine.STORKSAMLEngine; +import eu.stork.peps.exceptions.STORKSAMLEngineException; + +/** + * creates a STORK attribute request for a configurable set of attributes + */ +public class StorkAttributeRequestProvider extends AttributeProvider { + + private PersonalAttributeList requestedAttributes; + + /** The destination. */ + private String destination; + + /** The sp country code. */ + private String spCountryCode; + + /** + * Instantiates a new stork attribute request provider. + * + * @param apUrl the AP location + * @param supportedAttributes the supported attributes as csv + */ + public StorkAttributeRequestProvider(String apUrl, String supportedAttributes) { + super(supportedAttributes); + destination = apUrl; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#acquire(java.lang.String) + */ + @Override + protected IPersonalAttributeList acquire(PersonalAttribute attribute, String spCountyCode, IAuthData authData) + throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException { + + if (!attributes.contains(attribute.getName())) + throw new UnsupportedAttributeException(); + + this.spCountryCode = spCountyCode; + + requestedAttributes = new PersonalAttributeList(1); + requestedAttributes.add(attribute); + throw new ExternalAttributeRequestRequiredException(this); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#parse(javax.servlet.http.HttpServletRequest) + */ + public IPersonalAttributeList parse(HttpServletRequest httpReq) throws MOAIDException, UnsupportedAttributeException { + + Logger.info(this.getClass().getSimpleName() + " tries to extract SAMLResponse out of HTTP Request"); + + //extract STORK Response from HTTP Request + //Decodes SAML Response + byte[] decSamlToken; + try { + decSamlToken = PEPSUtil.decodeSAMLToken(httpReq.getParameter("SAMLResponse")); + } catch(NullPointerException e) { + throw new UnsupportedAttributeException(); + } + + //Get SAMLEngine instance + STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP"); + + STORKAttrQueryResponse attrResponse = null; + try { + //validate SAML Token + Logger.debug("Starting validation of SAML response"); + attrResponse = engine.validateSTORKAttrQueryResponse(decSamlToken, (String) httpReq.getRemoteHost()); + Logger.info("SAML response successfully verified!"); + }catch(STORKSAMLEngineException e){ + Logger.error("Failed to verify STORK SAML Response", e); + throw new MOAIDException("stork.05", null); + } + + return attrResponse.getPersonalAttributeList(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#performRedirect(java.lang.String) + */ + public void performRedirect(String url, HttpServletRequest req, HttpServletResponse resp, OAAuthParameter oaParam) throws MOAIDException { + + String spSector = "Business"; + String spInstitution = StringUtils.isEmpty(oaParam.getFriendlyName()) ? "UNKNOWN" : oaParam.getFriendlyName(); + String spApplication = spInstitution; + + //generate AuthnRquest + STORKAttrQueryRequest attributeRequest = new STORKAttrQueryRequest(); + attributeRequest.setDestination(destination); + attributeRequest.setAssertionConsumerServiceURL(url); + attributeRequest.setIssuer(HTTPUtils.getBaseURL(req)); + attributeRequest.setQaa(oaParam.getQaaLevel()); + attributeRequest.setSpInstitution(spInstitution); + attributeRequest.setCountry(spCountryCode); + attributeRequest.setSpCountry(spCountryCode); + attributeRequest.setSpApplication(spApplication); + attributeRequest.setSpSector(spSector); + attributeRequest.setPersonalAttributeList(requestedAttributes); + + attributeRequest.setCitizenCountryCode("AT"); + + + Logger.debug("STORK AttrRequest successfully assembled."); + + STORKSAMLEngine samlEngine = STORKSAMLEngine.getInstance("VIDP"); + try { + attributeRequest = samlEngine.generateSTORKAttrQueryRequest(attributeRequest); + } catch (STORKSAMLEngineException e) { + Logger.error("Could not sign STORK SAML AttrRequest.", e); + throw new MOAIDException("stork.00", null); + } + + Logger.info("STORK AttrRequest successfully signed!"); + + try { + Logger.trace("Initialize VelocityEngine..."); + + VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); + Template template = velocityEngine.getTemplate("/resources/templates/saml2-post-binding-moa.vm"); + VelocityContext context = new VelocityContext(); + context.put("SAMLRequest", PEPSUtil.encodeSAMLToken(attributeRequest.getTokenSaml())); + context.put("action", destination); + + StringWriter writer = new StringWriter(); + template.merge(context, writer); + + resp.getOutputStream().write(writer.toString().getBytes()); + } catch (Exception e) { + Logger.error("Error sending STORK SAML AttrRequest.", e); + throw new MOAIDException("stork.11", null); + } + Logger.info("STORK AttrRequest successfully rendered!"); + } + +} + |