aboutsummaryrefslogtreecommitdiff
path: root/id/server/modules/module-stork/src/main/java/at/gv/egovernment
diff options
context:
space:
mode:
Diffstat (limited to 'id/server/modules/module-stork/src/main/java/at/gv/egovernment')
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java367
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeProviderFactory.java101
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java531
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java249
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/CorporateBodyMandateContainer.java115
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DataContainer.java100
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ExternalAttributeRequestRequiredException.java53
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java248
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOASTORKRequest.java254
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOASTORKResponse.java296
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java182
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java602
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java132
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/S2Constants.java66
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java49
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKProtocol.java233
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/SimpleNamespaceContext.java83
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/UnsupportedAttributeException.java29
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/AttributeProvider.java139
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/EHvdAttributeProviderPlugin.java254
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java231
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java238
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java688
-rw-r--r--id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/StorkAttributeRequestProvider.java193
24 files changed, 5433 insertions, 0 deletions
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java
new file mode 100644
index 000000000..25cb952d7
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java
@@ -0,0 +1,367 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.SLOInformationImpl;
+import at.gv.egovernment.moa.id.data.SLOInformationInterface;
+import at.gv.egovernment.moa.id.moduls.IAction;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider;
+import at.gv.egovernment.moa.id.storage.AssertionStorage;
+import at.gv.egovernment.moa.logging.Logger;
+import eu.stork.peps.auth.commons.*;
+import eu.stork.peps.auth.engine.STORKSAMLEngine;
+import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType;
+import eu.stork.peps.exceptions.STORKSAMLEngineException;
+
+import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * The AttributeCollector Action tries to get all requested attributes from a set of {@link AttributeProvider} Plugins.
+ * The class is called whenever the {@link AuthenticationRequest} Action is invoked and checks for missing attributes.
+ * Furthermore, the class can handle direct posts. That is when the class triggers an attribute query which needs user
+ * interaction, redirect to another portal, etc. The redirect will hit here and the class can continue to fetch attributes.
+ *
+ * TODO how do we treat mandatory and optional attributes?
+ */
+public class AttributeCollector implements IAction {
+
+ /**
+ * The Constant ARTIFACT_ID.
+ */
+ private static final String ARTIFACT_ID = "artifactId";
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.auth.data.AuthenticationSession)
+ */
+ public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException {
+
+ // - fetch the container
+ String artifactId = (String) httpReq.getParameter(ARTIFACT_ID);
+ DataContainer container;
+ try {
+ container = AssertionStorage.getInstance().get(artifactId, DataContainer.class);
+ } catch (MOADatabaseException e) {
+ Logger.error("Error fetching incomplete Stork response from temporary storage. Most likely a timeout occured.", e);
+ throw new MOAIDException("stork.11", null);
+ }
+
+
+ if (httpReq.getParameter("SAMLResponse") != null) {
+ Logger.info("Got SAML response from external attribute provider.");
+
+ MOASTORKResponse STORK2Response = new MOASTORKResponse();
+
+ //extract STORK Response from HTTP Request
+ byte[] decSamlToken;
+ try {
+ decSamlToken = PEPSUtil.decodeSAMLToken(httpReq.getParameter("SAMLResponse"));
+ } catch (NullPointerException e) {
+ if (httpReq.getRemoteHost().contains("129.27.142")) {
+ Logger.warn("Availability check by " + httpReq.getRemoteHost() + " on URI: " + httpReq.getRequestURI());
+ } else {
+ Logger.error("Unable to retrieve STORK Request for host: " + httpReq.getRemoteHost() + " and URI: " + httpReq.getRequestURI(), e);
+ }
+ throw new MOAIDException("stork.04", null);
+ }
+
+ //Get SAMLEngine instance
+ STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
+
+ STORKAuthnResponse authnResponse = null;
+
+
+ // check if valid authn response is contained
+ try {
+ authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, httpReq.getRemoteAddr());
+ } catch (STORKSAMLEngineException ex) {
+ Logger.error("Unable to validate Stork AuthenticationResponse: " + ex.getMessage());
+ }
+
+ STORK2Response.setSTORKAuthnResponseToken(decSamlToken);
+
+ // check if the attributes are provided for the same person from request
+ // requires presence of eIdentifier for unambigious correlation
+ Logger.debug("Checking if the attribute relates to the correct person..");
+ try {
+ String remoteEIdentifier= authnResponse.getPersonalAttributeList().get("eIdentifier").getValue().get(0);
+ String localEidentifier= container.getResponse().getStorkAuthnResponse().getPersonalAttributeList().get("eIdentifier").getValue().get(0);
+ if (!remoteEIdentifier.equals(localEidentifier)) {
+ Logger.error("The attribute is not provided for the same person!");
+ throw new MOAIDException("stork.25", null);
+ }
+ } catch (NullPointerException ex) {
+ Logger.warn("Could not check the correlation of attributes from external provider. Ignoring the check.");
+ //Logger.debug(ex);
+ //throw new MOAIDException("stork.04", null); // TODO revise message, raise exception when ehvd checked
+ }
+
+ if (authnResponse.getPersonalAttributeList().size() > 0) {
+ Logger.info("Response from external attribute provider contains " + authnResponse.getPersonalAttributeList().size() + " attributes.");
+ container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), authnResponse.getPersonalAttributeList()));
+ }
+
+ }
+
+ // end addition
+
+
+ // read configuration parameters of OA
+ OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(container.getRequest().getAssertionConsumerServiceURL());
+ if (oaParam == null)
+ throw new AuthenticationException("stork.12", new Object[]{container.getRequest().getAssertionConsumerServiceURL()});
+
+ // find the attribute provider plugin that can handle the response
+ IPersonalAttributeList newAttributes = null;
+
+ Iterator<AttributeProvider> attibuteProvidersInterator = AttributeProviderFactory.getConfiguredPlugins(oaParam.getStorkAPs());
+ while(attibuteProvidersInterator.hasNext())
+ try {
+ newAttributes = attibuteProvidersInterator.next().parse(httpReq);
+
+ // stop as soon as we hit a capable plugin
+ break;
+ } catch (UnsupportedAttributeException e1) {
+ // the current provider cannot find anything familiar within the
+ // provided httpreq. Try the next one.
+ }
+
+ if (null == newAttributes) {
+ // we do not have a provider which is capable of fetching something
+ // from the received httpreq.
+ Logger.error("No attribute could be retrieved from the response the attribute provider gave us.");
+ }
+
+ // - insert the embedded attribute(s) into the container
+ if (null != newAttributes)
+ container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), newAttributes));
+
+ // see if we need some more attributes
+ SLOInformationImpl sloInfo = (SLOInformationImpl) processRequest(container, httpReq, httpResp, authData, oaParam);
+
+ if (sloInfo == null) {
+ sloInfo = new SLOInformationImpl(null, null, null, req.requestedModule());
+ }
+
+ return sloInfo;
+
+ }
+
+ /**
+ * Checks if there are missing attributes and tries to fetch them. If there are no more attribute to fetch,
+ * this very method creates and sends the protocol result to the asking S-PEPS.
+ *
+ * @param container the {@link DataContainer} representing the status of the overall query.
+ * @return the string
+ * @throws MOAIDException
+ */
+ public SLOInformationInterface processRequest(DataContainer container, HttpServletRequest request, HttpServletResponse response, IAuthData authData, OAAuthParameter oaParam) throws MOAIDException {
+ // check if there are attributes we need to fetch
+
+ IPersonalAttributeList requestAttributeList = container.getRequest().getPersonalAttributeList();
+ IPersonalAttributeList responseAttributeList = container.getResponse().getPersonalAttributeList();
+ List<PersonalAttribute> missingAttributes = new ArrayList<PersonalAttribute>();
+ Logger.debug("aquire list of missing attributes");
+ for (PersonalAttribute current : requestAttributeList)
+ if (!responseAttributeList.containsKey(current.getName())) {
+ if(null == current.getStatus() || (null != current.getStatus() && !current.getStatus().equals(AttributeStatusType.WITHHELD.value()))) {
+ // add the ones we need
+ missingAttributes.add(current);
+ Logger.debug("add " + current.getName() + " to the list of missing attributes");
+ }
+ } else {
+ // remove the ones we do not want to share from the response list
+ if(null != current.getStatus() && current.getStatus().equals(AttributeStatusType.WITHHELD.value())) {
+ responseAttributeList.remove(current.getName());
+ Logger.debug("remove " + current.getName() + " from the list of resulting attributes because the user does not want to disclose the data");
+ }
+ }
+
+ Logger.info("collecting attributes...");
+ Logger.debug("found " + missingAttributes.size() + " missing attributes");
+
+ // Try to get all missing attributes
+ try {
+ // for each attribute still missing
+ for (PersonalAttribute currentAttribute : missingAttributes) {
+
+ /*
+ * prefill attributes with "notAvailable". If we get them later, we override the value and status.
+ * This way, there is no error case in which an attribute is left unanswered.
+ */
+ IPersonalAttributeList aquiredAttributes = new PersonalAttributeList();
+ currentAttribute.setStatus(AttributeStatusType.NOT_AVAILABLE.value());
+ aquiredAttributes.add((PersonalAttribute) currentAttribute.clone());
+ container.getResponse().setPersonalAttributeList(
+ addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes));
+ // - check if we can find a suitable AttributeProvider Plugin
+
+ Iterator<AttributeProvider> attibuteProvidersInterator = AttributeProviderFactory.getConfiguredPlugins(oaParam.getStorkAPs());
+ while(attibuteProvidersInterator.hasNext()) {
+ AttributeProvider currentProvider = attibuteProvidersInterator.next();
+
+ // build a section of attribute provider's predefined attributes and missing attributes
+ // only missing attributes that can be handled by attribute provider will be sent to it
+ List<PersonalAttribute> currentProviderConfiguredAttributes = new ArrayList<PersonalAttribute>();
+ for (String attributeName : currentProvider.getSupportedAttributeNames()) {
+ for (PersonalAttribute missingAttribute : missingAttributes) {
+ if (missingAttribute.getName().equals(attributeName)) {
+ currentProviderConfiguredAttributes.add(missingAttribute);
+ break;
+ }
+ }
+ }
+
+ try {
+ // - hand over control to the suitable plugin
+ Logger.info(currentProvider.getClass().getSimpleName() + " called to handle attribute '" + currentAttribute.getName() + "'");
+
+ //aquiredAttributes = currentProvider.acquire(currentAttribute, container.getRequest().getSpCountry(), moasession);
+ //aquiredAttributes = currentProvider.acquire(missingAttributes, container.getRequest().getSpCountry(), moasession);
+ aquiredAttributes = currentProvider.acquire(currentProviderConfiguredAttributes, container.getRequest(), authData);
+
+ Logger.info(currentProvider.getClass().getSimpleName() + " can handle attribute '" + currentAttribute.getName() + "'");
+ break;
+ } catch (UnsupportedAttributeException e) {
+ // ok, try the next attributeprovider
+ Logger.info(currentProvider.getClass().getSimpleName() + " could not handle attribute '" + currentAttribute.getName() + "'");
+ } catch (MOAIDException e) {
+ // the current plugin had an error. Try the next one.
+ Logger.info(currentProvider.getClass().getSimpleName() + " could not handle attribute '" + currentAttribute.getName() + "' due to an error");
+ }
+ }
+
+ // check if we could fetch the attribute
+ if (null == aquiredAttributes) {
+ // if not
+ Logger.error("We have no suitable plugin for obtaining the attribute '" + currentAttribute.getName() + "'");
+ } else
+ // else, update any existing attributes
+ container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes));
+ }
+ Logger.info("collecting attributes done");
+
+ // ask for consent if necessary
+ new ConsentEvaluator().generateSTORKResponse(response, container);
+
+ return null; // AssertionId
+ // TODO
+
+ } catch (ExternalAttributeRequestRequiredException e) {
+ // the attribute request is ongoing and requires an external service.
+ try {
+ // memorize the container again
+ Logger.debug("prepare putting the container into temporary storage...");
+
+ // - generate new key
+ String newArtifactId = new SecureRandomIdentifierGenerator()
+ .generateIdentifier();
+ // - put container in temporary store.
+ AssertionStorage.getInstance().put(newArtifactId, container);
+
+ Logger.debug("...successful");
+
+ Logger.info(e.getAp().getClass().getSimpleName() + " is going to ask an external service provider for the requested attributes");
+
+ // add container-key to redirect embedded within the return URL
+ e.getAp().performRedirect(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/stork2/ResumeAuthentication?" + ARTIFACT_ID + "=" + newArtifactId, request, response, oaParam);
+
+ } catch (Exception e1) {
+ // TODO should we return the response as is to the PEPS?
+ Logger.error("Error putting incomplete Stork response into temporary storage", e1);
+ e1.printStackTrace();
+ throw new MOAIDException("stork.11", null);
+ }
+
+ //TODO: in case of Single LogOut -> SLO information has to be stored
+ return null; // TODO what to do here?
+ }
+ }
+
+ /**
+ * Adds or updates all {@link PersonalAttribute} objects given in {@code source} to/in {@code target}.
+ *
+ * @param target the target
+ * @param source the source
+ * @return
+ * @throws MOAIDException
+ */
+ private PersonalAttributeList addOrUpdateAll(IPersonalAttributeList target, IPersonalAttributeList source) throws MOAIDException {
+
+ PersonalAttributeList updatedList = new PersonalAttributeList();
+ for (PersonalAttribute el : target)
+ updatedList.add(el);
+
+ Logger.debug("Updating " + source.size() + " attributes...");
+ for (PersonalAttribute current : source) {
+ Logger.debug("treating " + current.getName());
+
+ // check if we need to update the current pa
+ if (updatedList.containsKey(current.getName())) {
+ PersonalAttribute existing = target.get(current.getName());
+ if(!(existing.isEmptyValue() && existing.isEmptyComplexValue()))
+ if(!(existing.getValue().equals(current.getValue()) || existing.getComplexValue().equals(current.getComplexValue()))) {
+ Logger.error("Attribute Value does not match the value from first authentication!");
+ throw new MOAIDException("stork.16", new Object[] {existing.getName()});
+ }
+
+ updatedList.get(current.getName()).setStatus(current.getStatus());
+ updatedList.get(current.getName()).setValue(current.getValue());
+ updatedList.get(current.getName()).setComplexValue(current.getComplexValue());
+ } else
+ updatedList.add(current);
+
+ Logger.debug("...successfully treated " + current.getName());
+ }
+
+ return updatedList;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IAction#needAuthentication(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) {
+ // this action does not need any authentication. The authentication is already done by the preceding AuthenticationRequest-Action.
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName()
+ */
+ public String getDefaultActionName() {
+ return STORKProtocol.ATTRIBUTE_COLLECTOR;
+ }
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeProviderFactory.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeProviderFactory.java
new file mode 100644
index 000000000..aadbbd959
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeProviderFactory.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import at.gv.egovernment.moa.id.commons.MOAIDConstants;
+import at.gv.egovernment.moa.id.config.stork.StorkAttributeProviderPlugin;
+import at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider;
+import at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.EHvdAttributeProviderPlugin;
+import at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.MandateAttributeRequestProvider;
+import at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.PVPAuthenticationProvider;
+import at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.SignedDocAttributeRequestProvider;
+import at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.StorkAttributeRequestProvider;
+import at.gv.egovernment.moa.logging.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.PriorityQueue;
+
+/**
+ * A factory for creating AttributeProvider objects.
+ */
+public class AttributeProviderFactory {
+
+ /**
+ * Gets the available plugins.
+ *
+ * @return the available plugins
+ */
+ public static List<String> getAvailablePlugins() {
+ return MOAIDConstants.ALLOWED_STORKATTRIBUTEPROVIDERS;
+ }
+
+ /**
+ * Creates an AttributeProvider object for the given shortname. Returns
+ * {@code null} if there is no such provider available.
+ *
+ * @param shortname the simpleName for the providers class
+ * @return the attribute provider
+ */
+ public static AttributeProvider create(String shortname, String url, String attributes) {
+ if (shortname.equals("StorkAttributeRequestProvider")) {
+ return new StorkAttributeRequestProvider(url, attributes);
+ } else if (shortname.equals("EHvdAttributeProvider")) {
+ return new EHvdAttributeProviderPlugin(url, attributes);
+ } else if (shortname.equals("SignedDocAttributeRequestProvider")) {
+ return new SignedDocAttributeRequestProvider(url, attributes);
+ } else if (shortname.equals("MandateAttributeRequestProvider")) {
+ try {
+ return new MandateAttributeRequestProvider(url, attributes);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return null;
+ }
+ } else if (shortname.equals("PVPAuthenticationProvider")) {
+ return new PVPAuthenticationProvider(url, attributes);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets fresh instances of the configured plugins.
+ *
+ * @param collection the configured a ps
+ * @return the configured plugins
+ */
+ public static Iterator<AttributeProvider> getConfiguredPlugins(
+ Collection<StorkAttributeProviderPlugin> collection) {
+
+ PriorityQueue<AttributeProvider> result = new PriorityQueue<AttributeProvider>();
+ for (StorkAttributeProviderPlugin current : collection) {
+
+ result.add(create(current.getName(), current.getUrl(), current.getAttributes()));
+ Logger.debug("Adding configured attribute provider: " + current.getClass().getName() + current.getName() + " at " + current.getUrl());
+ }
+
+ return result.iterator();
+ }
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java
new file mode 100644
index 000000000..59db5797d
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java
@@ -0,0 +1,531 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.SLOInformationImpl;
+import at.gv.egovernment.moa.id.data.SLOInformationInterface;
+import at.gv.egovernment.moa.id.moduls.IAction;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.storage.AssertionStorage;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
+import at.gv.egovernment.moa.id.util.client.mis.simple.MISMandate;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import eu.stork.peps.auth.commons.*;
+import eu.stork.peps.auth.engine.STORKSAMLEngine;
+import eu.stork.peps.exceptions.STORKSAMLEngineException;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+
+/**
+ * Second request step - after authentication of the user is done and moasession obtained,
+ * process request and forward the user further to PEPS and/or other entities
+ *
+ * @author bsuzic
+ */
+
+public class AuthenticationRequest implements IAction {
+
+
+ private VelocityEngine velocityEngine;
+ private MOASTORKRequest moaStorkRequest = null;
+
+
+ public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException {
+
+ if ((req instanceof MOASTORKRequest)) { // && ( ((MOASTORKRequest) req).getCitizenCountryCode() == null || ((MOASTORKRequest) req).getCitizenCountryCode().equals("AT") )) {
+
+ this.moaStorkRequest = (MOASTORKRequest) req;
+
+ Logger.debug("Entering MOASTORKRequest");
+ httpResp.reset();
+
+ //TODO: CHECK: req.getOAURL() should return the unique OA identifier
+ OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(req.getOAURL());
+ if (oaParam == null)
+ throw new AuthenticationException("stork.12", new Object[]{req.getOAURL()});
+
+ MOASTORKResponse moaStorkResponse = new MOASTORKResponse();
+
+ // check if it is attribute query
+ if (moaStorkRequest.isAttrRequest()) {
+ Logger.debug("Starting AttrQueryRequest");
+
+ moaStorkResponse.setSTORKAttrResponse(new STORKAttrQueryResponse());
+ }
+ // check if we have authentication request
+ else if (moaStorkRequest.isAuthnRequest()) {
+ Logger.debug("Starting AuthenticationRequest");
+ moaStorkResponse.setSTORKAuthnResponse(new STORKAuthnResponse());
+
+ //STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
+
+ // Logger.debug("Starting generation of SAML response");
+ // try {
+ // moaStorkResponse.setSTORKAuthnResponse(engine.generateSTORKAuthnResponse(moaStorkRequest.getStorkAuthnRequest(), moaStorkResponse.getStorkAuthnResponse(), httpReq.getRemoteAddr(), false));
+ // } catch (STORKSAMLEngineException ex) {
+ // Logger.error("Failed to generate STORK SAML Response", ex);
+ // throw new MOAIDException("stork.05", null); // TODO
+ // }
+
+ // Get personal attributtes from MOA/IdentityLink
+
+ //build STORK attributes from local authentication information
+ if (authData != null) {
+ int reqQaa = -1;
+ int authQaa = -1;
+ try {
+ reqQaa = moaStorkRequest.getStorkAuthnRequest().getQaa();
+ authQaa = Integer.valueOf(
+ authData.getQAALevel().substring(PVPConstants.STORK_QAA_PREFIX.length()));
+
+ if (reqQaa > authQaa) {
+ Logger.warn("Requested QAA level does not match to authenticated QAA level");
+ throw new MOAIDException("stork.21", new Object[]{reqQaa, authQaa});
+
+ }
+
+ } catch (MOAIDException e) {
+ throw e;
+
+ } catch (Exception e) {
+ if (Logger.isDebugEnabled())
+ Logger.warn("STORK QAA Level evaluation error", e);
+
+ else
+ Logger.warn("STORK QAA Level evaluation error (ErrorMessage="
+ + e.getMessage() + ")");
+
+ throw new MOAIDException("stork.21", new Object[]{reqQaa, authQaa});
+
+ }
+
+ moaStorkResponse.setPersonalAttributeList(populateAttributes(authData, oaParam));
+
+ }
+ }
+
+ //moaStorkResponse.setCountry(moaStorkRequest.getSpCountry());
+
+ // Prepare extended attributes
+ Logger.debug("Preparing data container");
+
+ // create fresh container
+ DataContainer container = new DataContainer();
+
+ // - fill in the request we extracted above
+ container.setRequest(moaStorkRequest);
+
+ // - fill in the partial response created above
+ container.setResponse(moaStorkResponse);
+
+ container.setRemoteAddress(httpReq.getRemoteAddr());
+
+ Logger.debug("Data container prepared");
+
+ if(oaParam.isRequireConsentForStorkAttributes())
+ new ConsentEvaluator().requestConsent(container, httpReq, httpResp, authData, oaParam);
+ else
+ new AttributeCollector().processRequest(container, httpReq, httpResp, authData, oaParam);
+
+ return null;
+ }
+// // check if we are getting request for citizen of some other country
+// else if (req instanceof MOASTORKRequest) {
+// return handleMOAStorkRequest("VIDP", (MOASTORKRequest) req, httpReq.getRemoteAddr(), httpResp);
+// }
+
+ // Check if we got the response from PEPS
+ // If so then process it and forward to SP
+ else if ((req instanceof MOASTORKResponse)) {
+ return handleMOAStorkResponse("VIDP", (MOASTORKResponse) req, httpReq.getRemoteAddr(), httpResp);
+ } else {
+ Logger.error("Could not recognize request.");
+ throw new MOAIDException("stork.15", null);
+ }
+ }
+
+ /*
+ Handles STORKAuthnRequeste received for citizens of other countries
+ */
+ private SLOInformationInterface handleMOAStorkRequest(String instanceName, MOASTORKRequest moastorkRequest, String remoteAddr, HttpServletResponse httpResp) throws MOAIDException {
+
+ STORKAuthnRequest spAuthnRequest = moastorkRequest.getStorkAuthnRequest();
+ STORKAuthnRequest storkAuthnRequest = null;
+
+ String citizenCountryCode = spAuthnRequest.getCitizenCountryCode();
+ Logger.info("Got authentication request for citizen of " + citizenCountryCode);
+
+ try {
+ storkAuthnRequest = (STORKAuthnRequest) spAuthnRequest.clone();
+ } catch (CloneNotSupportedException e) {
+ Logger.error("Could not clone AuthnRequest ", e);
+ throw new MOAIDException("stork.05", null); // TODO
+ }
+
+ //TODO: in case of Single LogOut -> SLO information has to be stored
+ // check if citizen country is configured in the system
+ if (!(AuthConfigurationProviderFactory.getInstance().getStorkConfig().getCpepsMap().containsKey(citizenCountryCode))) {
+ Logger.error("Citizen country PEPS not configured in MOA instance: " + citizenCountryCode);
+ throw new MOAIDException("stork.05", null); // TODO
+ }
+
+ // extracting basic settings and adjusting assertion consumer
+ String issuer = null;
+ String assertionConsumerURL = null;
+ String publicURLPrefix = null;
+ String destinationURL = null;
+
+ try {
+ issuer = new URL(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix()).toString();
+ destinationURL = AuthConfigurationProviderFactory.getInstance().getStorkConfig().getCPEPS(citizenCountryCode).getPepsURL().toString();
+ publicURLPrefix = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix();
+ assertionConsumerURL = publicURLPrefix + "/stork2/SendPEPSAuthnRequest";
+ } catch (MalformedURLException ex) {
+ Logger.error("Wrong PublicURLPrefix setting of MOA instance: " + AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(), ex);
+ throw new MOAIDException("stork.05", null); // TODO
+ } catch (Exception ex) {
+ Logger.error("Problem with PEPS configuration of MOA instance.", ex);
+ throw new MOAIDException("stork.05", null); // TODO
+ }
+
+
+ // drop if we do not have publicprefix url configured on the instance
+ if (publicURLPrefix == null)
+ throw new AuthenticationException("stork.12", new String[]{"PublicURLPrefix"});
+
+ // adjusting request
+ storkAuthnRequest.setEIDCrossBorderShare(spAuthnRequest.isEIDCrossBorderShare());
+ storkAuthnRequest.setEIDSectorShare(spAuthnRequest.isEIDSectorShare());
+ storkAuthnRequest.setEIDCrossSectorShare(spAuthnRequest.isEIDCrossSectorShare());
+ storkAuthnRequest.setCitizenCountryCode(spAuthnRequest.getCitizenCountryCode());
+ storkAuthnRequest.setIssuer(issuer);
+ storkAuthnRequest.setAssertionConsumerServiceURL(assertionConsumerURL);
+ storkAuthnRequest.setDestination(destinationURL);
+
+ // regenerate request
+ try {
+ //Get SAMLEngine instance
+ STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
+ Logger.debug("Starting generation of SAML request");
+ storkAuthnRequest = engine.generateSTORKAuthnRequest(storkAuthnRequest);
+
+ //generateSAML Token
+ Logger.info("SAML response succesfully generated!");
+ } catch (STORKSAMLEngineException e) {
+ Logger.error("Failed to generate STORK SAML Response", e);
+ throw new MOAIDException("stork.05", null);
+ }
+
+ // store original request from SP in order to be able to extract it in later iteration/response
+ DataContainer spRequestContainer = new DataContainer();
+ spRequestContainer.setRequest(moastorkRequest);
+
+ try {
+ AssertionStorage.getInstance().put(storkAuthnRequest.getSamlId(), spRequestContainer);
+ Logger.info("Storing artifactId " + storkAuthnRequest.getSamlId() + " of SP authentication request with id " + spAuthnRequest.getSamlId());
+ } catch (MOADatabaseException e) {
+ e.printStackTrace();
+ }
+
+ // preparing redirection for the client
+ performRedirection("SAMLRequest", destinationURL, storkAuthnRequest.getTokenSaml(), httpResp);
+
+ SLOInformationImpl sloInfo = new SLOInformationImpl();
+ sloInfo.setProtocolType(moastorkRequest.requestedModule());
+ return sloInfo;
+ }
+
+ /*
+ Handles STORKAuthnResponse received from PEPS (return to SP)
+ */
+ private SLOInformationInterface handleMOAStorkResponse(String instanceName, MOASTORKResponse moastorkResponse, String remoteAddr, HttpServletResponse httpResp) throws MOAIDException {
+
+ STORKAuthnResponse authnResponse = null;
+
+ //Get SAMLEngine instance
+ STORKSAMLEngine engine = STORKSAMLEngine.getInstance(instanceName);
+
+ try {
+ authnResponse = engine.validateSTORKAuthnResponse(moastorkResponse.getSTORKAuthnResponseToken(), remoteAddr);
+ } catch (STORKSAMLEngineException ex) {
+ Logger.error("Unable to validate Stork AuthenticationResponse: " + ex.getMessage());
+ throw new MOAIDException("stork.15", null); // TODO
+ }
+
+ Logger.debug("Requesting artifactId " + authnResponse.getInResponseTo() + " from store.");
+
+ DataContainer dataContainer = null;
+ try {
+ dataContainer = AssertionStorage.getInstance().get(authnResponse.getInResponseTo(), DataContainer.class);
+ } catch (MOADatabaseException e) {
+ Logger.error("Unable to retrieve datacontainer with reference authentication request. Database exception.");
+ throw new MOAIDException("stork.15", null); // TODO
+ }
+
+ // setting new reference request and return url
+ authnResponse.setInResponseTo(dataContainer.getRequest().getStorkAuthnRequest().getSamlId());
+ authnResponse.setAudienceRestriction(dataContainer.getRequest().getAssertionConsumerServiceURL());
+ //AudienceRestrictionBuilder audienceRestrictionBuilder = new AudienceRestrictionBuilder();
+ //AudienceRestriction audienceRestriction = audienceRestrictionBuilder.buildObject(dataContainer.getRequest().getAssertionConsumerServiceURL(), "localname", "nameprefix");
+
+ //authnResponse.getAssertions().get(0).getConditions().getAudienceRestrictions().add(audienceRestriction);
+
+ Logger.debug("Starting generation of SAML response");
+ try {
+ authnResponse = engine.generateSTORKAuthnResponse(dataContainer.getRequest().getStorkAuthnRequest(), authnResponse, remoteAddr, false);
+ } catch (STORKSAMLEngineException e) {
+ Logger.error("Failed to generate STORK SAML Response", e);
+ throw new MOAIDException("stork.05", null); // TODO check
+ }
+
+ Logger.info("SAML response succesfully generated.");
+
+ // preparing redirection for the client
+ performRedirection("SAMLResponse", dataContainer.getRequest().getAssertionConsumerServiceURL(), authnResponse.getTokenSaml(), httpResp);
+
+ return null;
+ }
+
+ /*
+ Perform redirection of the client based on post binding
+ */
+ private void performRedirection(String actionType, String assertionConsumerURL, byte[] tokenSaml, HttpServletResponse httpResp) throws MOAIDException {
+ Logger.info("Performing redirection, using action type: " + actionType);
+
+ try {
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html");
+ VelocityContext context = new VelocityContext();
+
+ context.put(actionType, PEPSUtil.encodeSAMLToken(tokenSaml));
+ Logger.debug("Encoded " + actionType + " original: " + new String(tokenSaml));
+
+ Logger.debug("Using assertion consumer url as action: " + assertionConsumerURL);
+ context.put("action", assertionConsumerURL);
+
+ Logger.debug("Starting template merge");
+ StringWriter writer = new StringWriter();
+
+ Logger.debug("Doing template merge");
+ template.merge(context, writer);
+ Logger.debug("Template merge done");
+
+ Logger.debug("Sending html content: " + writer.getBuffer().toString());
+ Logger.debug("Sending html content2 : " + new String(writer.getBuffer()));
+
+ httpResp.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8"));
+
+ } catch (IOException e) {
+ Logger.error("Velocity IO error: " + e.getMessage());
+ throw new MOAIDException("stork.15", null); // TODO
+ } catch (Exception e) {
+ Logger.error("Velocity general error: " + e.getMessage());
+ throw new MOAIDException("stork.15", null); // TODO
+ }
+
+ }
+
+ public void generatePEPSRedirect(HttpServletResponse httpResp, DataContainer container) throws MOAIDException {
+ MOASTORKRequest request = container.getRequest();
+ MOASTORKResponse response = container.getResponse();
+
+ Logger.info("generating stork response...");
+
+ try {
+ //Get SAMLEngine instance
+ STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
+ Logger.debug("Starting generation of SAML response");
+ if (response.isAuthnResponse())
+ response.setSTORKAuthnResponse(engine.generateSTORKAuthnResponse(request.getStorkAuthnRequest(), response.getStorkAuthnResponse(), container.getRemoteAddress(), false));
+ else
+ response.setSTORKAttrResponse(engine.generateSTORKAttrQueryResponse(request.getStorkAttrQueryRequest(), response.getStorkAttrQueryResponse(), container.getRemoteAddress(), "", false));
+
+
+ //generateSAML Token
+ Logger.info("SAML response succesfully generated!");
+ } catch (STORKSAMLEngineException e) {
+ Logger.error("Failed to generate STORK SAML Response", e);
+ throw new MOAIDException("stork.05", null);
+ }
+
+ // preparing redirection for the client
+ try {
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html");
+ VelocityContext context = new VelocityContext();
+
+ byte[] blob;
+ if (request.isAttrRequest())
+ blob = response.getStorkAttrQueryResponse().getTokenSaml();
+ else
+ blob = response.getStorkAuthnResponse().getTokenSaml();
+
+ context.put("SAMLResponse", PEPSUtil.encodeSAMLToken(blob));
+ Logger.debug("SAMLResponse original: " + new String(blob));
+
+ Logger.debug("Putting assertion consumer url as action: " + request.getAssertionConsumerServiceURL());
+ context.put("action", request.getAssertionConsumerServiceURL());
+ 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());
+ Logger.trace("Sending html content2 : " + new String(writer.getBuffer()));
+
+ httpResp.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8"));
+
+ } catch (Exception e) {
+ Logger.error("Velocity error: " + e.getMessage());
+ }
+ }
+
+
+ public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) {
+
+ //redirect to national PVP IDP infrastructure if special attributes are requested
+ if (MiscUtil.isEmpty(req.getRequestedIDP()) && req instanceof MOASTORKRequest)
+ return !STORKPVPUtilits.performAuthenticationOnNationalIDP((MOASTORKRequest) req);
+
+// // authentication is not needed if we have authentication request from SP for citizen of configured PEPS country
+// if (req instanceof MOASTORKRequest) {
+// MOASTORKRequest moastorkRequest = (MOASTORKRequest) req;
+// if (moastorkRequest.getStorkAuthnRequest() != null) {
+// String citizenCountryCode = moastorkRequest.getStorkAuthnRequest().getCitizenCountryCode();
+// // check if citizen country is configured in the system
+// try {
+// if (AuthConfigurationProvider.getInstance().getStorkConfig().getCpepsMap().containsKey(citizenCountryCode)) {
+// return false;
+// }
+// } catch (MOAIDException e) {
+// Logger.error("Could not initialize AuthConfigurationProvider");
+// }
+// }
+// // authentication is not required if received authentication response
+// } else if (req instanceof MOASTORKResponse) {
+// return false;
+// }
+
+ return true;
+ }
+
+
+ private void iterate(NamedNodeMap attributesList) {
+ for (int j = 0; j < attributesList.getLength(); j++) {
+ Logger.debug("--Attribute: "
+ + attributesList.item(j).getNodeName() + " = "
+ + attributesList.item(j).getNodeValue());
+ }
+ }
+
+
+ // does nothing
+ public void mandate(IAuthData authData) {
+
+ if (authData.isUseMandate()) {
+ try {
+ MISMandate mandate = authData.getMISMandate();
+ String owbpk = mandate.getOWbPK();
+ byte[] mand = mandate.getMandate();
+ String profprep = mandate.getProfRep();
+ //String textdesc = mandate.getTextualDescriptionOfOID();
+ Element mndt = authData.getMandate();
+
+ iterate(mndt.getAttributes());
+ Logger.debug("mandate encoded: " + new String(org.bouncycastle.util.encoders.Base64.encode(mand)));
+ } catch (Exception x) {
+ Logger.debug("There is no mandate used in transaction");
+ }
+ }
+
+
+ }
+
+ public PersonalAttributeList populateAttributes(IAuthData authData, IOAAuthParameters oaParam) {
+
+ IPersonalAttributeList attrLst = moaStorkRequest.getStorkAuthnRequest().getPersonalAttributeList();
+ Logger.info("Found " + attrLst.size() + " personal attributes in the request.");
+
+ // Define attribute list to be populated
+ PersonalAttributeList attributeList = new PersonalAttributeList();
+ MOAAttributeProvider moaAttributeProvider = new MOAAttributeProvider(authData, moaStorkRequest);
+
+ try {
+ for (PersonalAttribute personalAttribute : attrLst) {
+ try {
+ Logger.debug("Personal attribute found in request: " + personalAttribute.getName() + " isRequired: " + personalAttribute.isRequired());
+ moaAttributeProvider.populateAttribute(attributeList, personalAttribute);
+ } catch (Exception e) {
+ Logger.error("Exception, attributes: " + e.getMessage(), e);
+ }
+ }
+ } catch (Exception e) {
+ Logger.error("Exception, attributes: " + e.getMessage(), e);
+ }
+
+ Logger.trace("AUTHBLOCK " + authData.getAuthBlock());
+ Logger.debug("SESSION IDENTIFIER " + authData.getCcc() + " " + oaParam.getIdentityLinkDomainIdentifier());
+
+ return attributeList;
+ }
+
+ public String getDefaultActionName() {
+ return STORKProtocol.AUTHENTICATIONREQUEST;
+ }
+
+
+ private void initVelocityEngine() throws Exception {
+ velocityEngine = new VelocityEngine();
+ velocityEngine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8");
+ velocityEngine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8");
+ velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
+ velocityEngine.setProperty("classpath.resource.loader.class",
+ "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+
+ velocityEngine.init();
+ }
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java
new file mode 100644
index 000000000..bde0f362d
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import java.io.StringWriter;
+
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.SLOInformationInterface;
+import at.gv.egovernment.moa.id.moduls.IAction;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.storage.AssertionStorage;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import eu.stork.peps.auth.commons.PEPSUtil;
+import eu.stork.peps.auth.commons.PersonalAttribute;
+import eu.stork.peps.auth.engine.STORKSAMLEngine;
+import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType;
+import eu.stork.peps.exceptions.STORKSAMLEngineException;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * The ConsentEvaluator assists with fetching user consent on the list of attributes to be sent to the asking S-PEPS.
+ */
+public class ConsentEvaluator implements IAction {
+
+ /**
+ * The Constant ARTIFACT_ID.
+ */
+ private static final String ARTIFACT_ID = "artifactId";
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.auth.data.AuthenticationSession)
+ */
+ public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException {
+
+ // - fetch the container
+ String artifactId = (String) httpReq.getParameter(ARTIFACT_ID);
+ DataContainer container;
+ try {
+ container = AssertionStorage.getInstance().get(artifactId, DataContainer.class);
+ req = container.getRequest();
+ } catch (MOADatabaseException e) {
+ Logger.error("Error fetching incomplete Stork response from temporary storage. Most likely a timeout occured.", e);
+ throw new MOAIDException("stork.17", null);
+ }
+
+ // evaluate response
+ for(PersonalAttribute current : container.getRequest().getPersonalAttributeList()) {
+ if(null == httpReq.getParameter(current.getName())) {
+ current.setStatus(AttributeStatusType.WITHHELD.value());
+ current.setValue(new ArrayList<String>());
+ current.setComplexValue(new HashMap<String, String>());
+ }
+ }
+
+ //TODO: CHECK: req.getOAURL() should return the unique OA identifier
+ OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(req.getOAURL());
+ if (oaParam == null)
+ throw new AuthenticationException("stork.12", new Object[]{req.getOAURL()});
+
+ new AttributeCollector().processRequest(container, httpReq, httpResp, authData, oaParam);
+
+ return null; // AssertionId
+ }
+
+ /**
+ * Fills the given HttpResponse with the required web page.
+ *
+ * @param container the container
+ * @param authData
+ * @param response the response
+ * @param oaParam the oa param
+ * @return the string
+ * @throws MOAIDException the mOAID exception
+ */
+ public String requestConsent(DataContainer container, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData, OAAuthParameter oaParam) throws MOAIDException {
+ //check if we need to collect consent
+ if(!oaParam.isRequireConsentForStorkAttributes()) {
+ (new AttributeCollector()).processRequest(container, httpReq, httpResp, authData, oaParam);
+ return "";
+ }
+
+ // prepare redirect
+ String newArtifactId;
+ try {
+
+ // memorize the container again
+ Logger.debug("prepare putting the container into temporary storage...");
+
+ // - generate new key
+ newArtifactId = new SecureRandomIdentifierGenerator().generateIdentifier();
+
+ // - put container in temporary store.
+ AssertionStorage.getInstance().put(newArtifactId, container);
+
+ Logger.debug("...successful");
+
+ } catch (Exception e1) {
+ // TODO should we return the response as is to the PEPS?
+ e1.printStackTrace();
+ Logger.error("Error putting incomplete Stork response into temporary storage", e1);
+ throw new MOAIDException("stork.17", null);
+ }
+
+ // ask for consent
+ try {
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/stork2_consent.html");
+ VelocityContext context = new VelocityContext();
+
+ context.put("action", AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/stork2/CompleteAuthentication?" + ARTIFACT_ID + "=" + newArtifactId);
+
+ // assemble table
+ String table = "";
+ for (PersonalAttribute current : container.getRequest().getPersonalAttributeList())
+ table += "<tr><td><input type=\"checkbox\" checked=\"yes\" name=\"" + current.getName() + "\"></td><td>" + current.getName() + (current.isRequired() ? "" : " (optional)") + "</td></tr>\n";
+
+ context.put("tablecontent", table);
+ for(Entry<String, String> current : oaParam.getFormCustomizaten().entrySet())
+ context.put(current.getKey().replace("#", ""), current.getValue());
+
+ StringWriter writer = new StringWriter();
+ template.merge(context, writer);
+ httpResp.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8"));
+
+ } catch (Exception e) {
+ Logger.error("Velocity error: " + e.getMessage());
+ throw new MOAIDException("stork.17", null);
+ }
+
+ return "12345"; // AssertionId
+ }
+
+ /**
+ * generates binary response from given response class and fill the given HttpResponse with a SAML Post Binding template.
+ *
+ * @param httpResp the http resp
+ * @param container the container
+ * @throws MOAIDException the mOAID exception
+ */
+ public void generateSTORKResponse(HttpServletResponse httpResp, DataContainer container) throws MOAIDException {
+ MOASTORKRequest request = container.getRequest();
+ MOASTORKResponse response = container.getResponse();
+
+ Logger.info("generating stork response...");
+
+ try {
+ //Get SAMLEngine instance
+ STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
+ Logger.debug("Starting generation of SAML response");
+ if(response.isAuthnResponse())
+ response.setSTORKAuthnResponse(engine.generateSTORKAuthnResponse(request.getStorkAuthnRequest(), response.getStorkAuthnResponse(), container.getRemoteAddress(), false));
+ else
+ response.setSTORKAttrResponse(engine.generateSTORKAttrQueryResponse(request.getStorkAttrQueryRequest(), response.getStorkAttrQueryResponse(), container.getRemoteAddress(), "", false));
+
+
+ //generateSAML Token
+ Logger.info("SAML response succesfully generated!");
+ } catch (STORKSAMLEngineException e) {
+ Logger.error("Failed to generate STORK SAML Response", e);
+ throw new MOAIDException("stork.05", null);
+ }
+
+ // preparing redirection for the client
+ try {
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html");
+ VelocityContext context = new VelocityContext();
+
+ byte[] blob;
+ if(request.isAttrRequest())
+ blob = response.getStorkAttrQueryResponse().getTokenSaml();
+ else
+ blob = response.getStorkAuthnResponse().getTokenSaml();
+
+ context.put("SAMLResponse", PEPSUtil.encodeSAMLToken(blob));
+ Logger.debug("SAMLResponse original: " + new String(blob));
+
+ Logger.debug("Putting assertion consumer url as action: " + request.getAssertionConsumerServiceURL());
+ context.put("action", request.getAssertionConsumerServiceURL());
+ 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());
+ Logger.trace("Sending html content2 : " + new String(writer.getBuffer()));
+
+ httpResp.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8"));
+
+ } catch (Exception e) {
+ Logger.error("Velocity error: " + e.getMessage());
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IAction#needAuthentication(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) {
+ // this action does not need any authentication. The authentication is already done by the preceding AuthenticationRequest-Action.
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName()
+ */
+ public String getDefaultActionName() {
+ return STORKProtocol.CONSENT_EVALUATOR;
+ }
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/CorporateBodyMandateContainer.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/CorporateBodyMandateContainer.java
new file mode 100644
index 000000000..acbf1678a
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/CorporateBodyMandateContainer.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.logging.Logger;
+import org.xml.sax.InputSource;
+
+import javax.xml.xpath.XPathExpressionException;
+import java.io.StringReader;
+/**
+ * Physical person representing corporate body
+ *
+ * @author bsuzic
+ * Date: 4/29/14, Time: 3:40 PM
+ */
+public class CorporateBodyMandateContainer extends MandateContainer {
+
+ protected String corpMandatorIdentificationValue = null;
+ protected String corpMandatorIdentificationType = null;
+ protected String corpMandatorFullName = null;
+
+
+ String localMethods[] = new String[]{"getCorpMandatorIdentificationValue", "getCorpMandatorIdentificationType", "getCorpMandatorFullName",
+ "getMandateIssuePlace", "getMandateIssueDate", "getMandateIssueTime", "getSimpleMandateContent", "getMandateValidFrom",
+ "getMandateValidTo", "getPhysicalRepresentativeIdentificationValue", "getPhysicalRepresentativeIdentificationType", "getAnnotation",
+ "getPhysicalRepresentativeGivenName", "getPhysicalRepresentativeFamilyName", "getPhysicalRepresentativeBirthDate"
+ };
+
+ public CorporateBodyMandateContainer(String mandate) throws XPathExpressionException, MOAIDException {
+ super(mandate);
+ Logger.debug("Initializing corporate body mandate container.");
+
+ setAnnotation(xPath.evaluate(S2Constants.MANDATE_ANNOTATION_QUERY, new InputSource(new StringReader(mandate))));
+ setCorpMandatorFullName(xPath.evaluate(S2Constants.MANDATE_MANDATOR_CORPBODY_FULLNAME_QUERY, new InputSource(new StringReader(mandate))));
+ setCorpMandatorIdentificationType(xPath.evaluate(S2Constants.MANDATE_MANDATOR_CORPBODY_IDTYPE_QUERY, new InputSource(new StringReader(mandate))));
+ setCorpMandatorIdentificationValue(xPath.evaluate(S2Constants.MANDATE_MANDATOR_CORPBODY_IDVALUE_QUERY, new InputSource(new StringReader(mandate))));
+ setMandateIssueDate(xPath.evaluate(S2Constants.MANDATE_ISSUEDDATE_QUERY, new InputSource(new StringReader(mandate))));
+ setMandateIssuePlace(xPath.evaluate(S2Constants.MANDATE_ISSUEDPLACE_QUERY, new InputSource(new StringReader(mandate))));
+ setMandateIssueTime(xPath.evaluate(S2Constants.MANDATE_ISSUEDTIME_QUERY, new InputSource(new StringReader(mandate))));
+ setMandateValidFrom(xPath.evaluate(S2Constants.MANDATE_SIMPLEMANDATECONTENT_VALIDFROM_QUERY, new InputSource(new StringReader(mandate))));
+ setMandateValidTo(xPath.evaluate(S2Constants.MANDATE_SIMPLEMANDATECONTENT_VALIDTO_QUERY, new InputSource(new StringReader(mandate))));
+ setPhysicalRepresentativeBirthDate(xPath.evaluate(S2Constants.MANDATE_REPRESENTATIVE_PHYPERS_DATEOFBIRTH_QUERY, new InputSource(new StringReader(mandate))));
+ setPhysicalRepresentativeFamilyName(xPath.evaluate(S2Constants.MANDATE_REPRESENTATIVE_PHYPERS_FAMILYNAME_QUERY, new InputSource(new StringReader(mandate))));
+ setPhysicalRepresentativeGivenName(xPath.evaluate(S2Constants.MANDATE_REPRESENTATIVE_PHYPERS_GIVENNAME_QUERY, new InputSource(new StringReader(mandate))));
+ setPhysicalRepresentativeIdentificationType(xPath.evaluate(S2Constants.MANDATE_REPRESENTATIVE_PHYPERS_IDTYPE_QUERY, new InputSource(new StringReader(mandate))));
+ setPhysicalRepresentativeIdentificationValue(xPath.evaluate(S2Constants.MANDATE_REPRESENTATIVE_PHYPERS_IDVALUE_QUERY, new InputSource(new StringReader(mandate))));
+ setSimpleMandateContent(xPath.evaluate(S2Constants.MANDATE_SIMPLEMANDATECONTENT_TXTDESC_QUERY, new InputSource(new StringReader(mandate))));
+
+ // check if all necessary fields are present
+ Logger.debug("Starting mandate structure validation");
+ try {
+ validateMandateStructure(localMethods); // TODO
+ } catch (Exception e) {
+
+ if (e instanceof MOAIDException) {
+ Logger.error("Could not validate mandate structure.");
+ throw new MOAIDException("stork.16", new Object[] {e.getMessage()}); // TODO
+ } else {
+ Logger.error("Error during mandate structure validation.");
+ throw new MOAIDException("stork.16", new Object[] {e.getMessage()}); // TODO
+ }
+
+ }
+
+ }
+
+ public String getCorpMandatorIdentificationValue() {
+ return corpMandatorIdentificationValue;
+ }
+
+ public void setCorpMandatorIdentificationValue(String corpMandatorIdentificationValue) {
+ Logger.debug("Setting corpMandatorIdentificationValue to AT/" + corpMandatorIdentificationValue);
+ this.corpMandatorIdentificationValue = "AT/" + corpMandatorIdentificationValue;
+ }
+
+ public String getCorpMandatorIdentificationType() {
+ return corpMandatorIdentificationType;
+ }
+
+ public void setCorpMandatorIdentificationType(String corpMandatorIdentificationType) {
+ this.corpMandatorIdentificationType = corpMandatorIdentificationType;
+ }
+
+ public String getCorpMandatorFullName() {
+ return corpMandatorFullName;
+ }
+
+ public void setCorpMandatorFullName(String corpMandatorFullName) {
+ this.corpMandatorFullName = corpMandatorFullName;
+ }
+
+
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DataContainer.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DataContainer.java
new file mode 100644
index 000000000..e01a7526a
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DataContainer.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import java.io.Serializable;
+
+/**
+ * Holds info about an ongoing but yet incomplete stork authnrequest process.
+ */
+public class DataContainer implements Serializable {
+
+ /** The Constant serialVersionUID. */
+ private static final long serialVersionUID = -8765997480582363012L;
+
+ /** The incoming request. */
+ private MOASTORKRequest request;
+
+ /** The yet incomplete response. */
+ private MOASTORKResponse response;
+
+ /** The target. */
+ private String target;
+
+ /** The remote address. */
+ private String remoteAddress;
+
+ /**
+ * Gets the request.
+ *
+ * @return the request
+ */
+ public MOASTORKRequest getRequest() {
+ return request;
+ }
+
+ /**
+ * Sets the request.
+ *
+ * @param moaStorkRequest the new request
+ */
+ public void setRequest(MOASTORKRequest moaStorkRequest) {
+ this.request = moaStorkRequest;
+ }
+
+ /**
+ * Gets the response.
+ *
+ * @return the response
+ */
+ public MOASTORKResponse getResponse() {
+ return response;
+ }
+
+ /**
+ * Sets the response.
+ *
+ * @param moaStorkResponse the new response
+ */
+ public void setResponse(MOASTORKResponse moaStorkResponse) {
+ this.response = moaStorkResponse;
+ }
+
+ /**
+ * Gets the remote address.
+ *
+ * @return the remote address
+ */
+ public String getRemoteAddress() {
+ return remoteAddress;
+ }
+
+ /**
+ * Sets the remote address.
+ *
+ * @param remoteAddress the new remote address
+ */
+ public void setRemoteAddress(String remoteAddress) {
+ this.remoteAddress = remoteAddress;
+ }
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ExternalAttributeRequestRequiredException.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ExternalAttributeRequestRequiredException.java
new file mode 100644
index 000000000..096f223d7
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ExternalAttributeRequestRequiredException.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider;
+
+public class ExternalAttributeRequestRequiredException extends Exception {
+
+ /** The Constant serialVersionUID. */
+ private static final long serialVersionUID = 5207631348933518908L;
+
+ /** The ap. */
+ private AttributeProvider ap;
+
+ /**
+ * Instantiates a new external attribute request required exception.
+ *
+ * @param provider the provider
+ */
+ public ExternalAttributeRequestRequiredException(AttributeProvider provider) {
+ ap = provider;
+ }
+
+ /**
+ * Gets the ap that caused the exception.
+ *
+ * @return the ap
+ */
+ public AttributeProvider getAp() {
+ return ap;
+ }
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java
new file mode 100644
index 000000000..2c7e5b539
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import at.gv.egovernment.moa.id.auth.builder.BPKBuilder;
+import at.gv.egovernment.moa.id.auth.exception.BuildException;
+import at.gv.egovernment.moa.id.data.AuthenticationRole;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import eu.stork.peps.auth.commons.PersonalAttribute;
+import eu.stork.peps.auth.commons.PersonalAttributeList;
+import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType;
+import org.joda.time.Period;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * @author bsuzic
+ * Date: 2/19/14, Time: 4:42 PM
+ *
+ * @author tlenz
+ * Date: 23.10.14
+ */
+public class MOAAttributeProvider {
+ private final IAuthData authData;
+ private static final Map<String, String> storkAttributeSimpleMapping;
+ private static final Map<String, String> storkAttributeFunctionMapping;
+ private final MOASTORKRequest moastorkRequest;
+
+ // mappings for attribute population methods
+ // based on mapping of moa authndata and executing functions to extract attributes
+ static {
+ Map<String, String> tempSimpleMap = new HashMap<String, String>();
+ tempSimpleMap.put("givenName", "getGivenName");
+ tempSimpleMap.put("surname", "getFamilyName");
+ tempSimpleMap.put("MSOrganization", "getPvpAttribute_OU");
+ storkAttributeSimpleMapping = Collections.unmodifiableMap(tempSimpleMap);
+
+ Map<String, String> tempFunctionMap = new HashMap<String, String>();
+ tempFunctionMap.put("eIdentifier", "geteIdentifier");
+ tempFunctionMap.put("ECApplicationRole","getECApplicationRole");
+ tempFunctionMap.put("dateOfBirth", "getFormatedDateOfBirth");
+ tempFunctionMap.put("MSOrganization", "getMSOrganization");
+ tempFunctionMap.put("age", "getAge");
+ tempFunctionMap.put("isAgeOver", "getIsAgeOver");
+ tempFunctionMap.put("citizenQAALevel", "getQAALevel");
+ storkAttributeFunctionMapping = Collections.unmodifiableMap(tempFunctionMap);
+
+ }
+
+ public MOAAttributeProvider(IAuthData authData, MOASTORKRequest moastorkRequest) {
+ this.authData = authData;
+ this.moastorkRequest = moastorkRequest;
+
+ }
+
+ public void populateAttribute(PersonalAttributeList attributeList, PersonalAttribute requestedAttribute ) {
+ String storkAttribute = requestedAttribute.getName();
+
+ // TODO: check if authData gets populated with stork attributtes during previous steps; it seems it is not
+ if (null != authData && null != authData.getStorkAttributes() && authData.getStorkAttributes().containsKey(requestedAttribute.getName())) {
+ Logger.debug("Trying to get value for attribute directly from STORK2 response [" + storkAttribute + "]");
+ try {
+ PersonalAttribute tmp = authData.getStorkAttributes().get(requestedAttribute.getName());
+ attributeList.add((PersonalAttribute) tmp.clone());
+ } catch(Exception e) {
+ Logger.error("Could not retrieve attribute from STORK2 response: " + storkAttribute);
+ Logger.debug(e);
+ }
+ } else if (storkAttributeSimpleMapping.containsKey(storkAttribute)) {
+ Logger.debug("Trying to get value for attribute using simple mapping [" + storkAttribute + "]");
+ try {
+ Method method = authData.getClass().getDeclaredMethod(storkAttributeSimpleMapping.get(storkAttribute));
+ populateAttributeWithMethod(method, authData, attributeList, storkAttribute, requestedAttribute);
+ } catch (NoSuchMethodException e) {
+ Logger.error("Could not found MOA extraction method while getting attribute: " + storkAttribute);
+ Logger.debug(e);
+ } catch (NullPointerException e) {
+ Logger.error("Error getting MOA extraction method while getting attribute: " + storkAttribute);
+ Logger.debug(e);
+ }
+
+ } else if (storkAttributeFunctionMapping.containsKey(storkAttribute)) {
+
+ Logger.debug("Trying to get value for attribute using function mapping [" + storkAttribute + "]");
+ try {
+ Method method = this.getClass().getDeclaredMethod(storkAttributeFunctionMapping.get(storkAttribute), PersonalAttribute.class);
+ populateAttributeWithMethod(method, this, attributeList, storkAttribute, requestedAttribute);
+ } catch (NoSuchMethodException e) {
+ Logger.error("Could not found MOA extraction method while getting attribute: " + storkAttribute);
+ }
+ } else {
+ Logger.debug("MOA method for extraction of attribute " + storkAttribute + " not defined.");
+ }
+ }
+
+ private String getAge(PersonalAttribute personalAttribute) {
+ if (authData.getDateOfBirth() != null) {
+ Integer age = new Period(authData.getDateOfBirth().getTime(), Calendar.getInstance().getTime().getTime()).getYears();
+ return age >= 0 ? age.toString() : null;
+ }
+ return null; // WP4 D4.2, Table 12:age, description - considerations
+ }
+
+ private String getIsAgeOver(PersonalAttribute personalAttribute)
+ {
+ try {
+ if ((authData.getDateOfBirth() != null) && (personalAttribute.getValue() != null) && (personalAttribute.getValue().size() > 0)) {
+ Integer ageOver = Integer.parseInt(personalAttribute.getValue().get(0));
+ Integer age = new Period(authData.getDateOfBirth().getTime(), Calendar.getInstance().getTime().getTime()).getYears();
+ return age >= ageOver ? ageOver.toString() : "";
+ }
+ } catch (Exception ex) {
+ Logger.error("Error encountered when determining isAgeOver");
+ Logger.debug(ex);
+ }
+ return null;
+ }
+
+ public String getQAALevel(PersonalAttribute personalAttribute) {
+ if (authData.getQAALevel().startsWith(PVPConstants.STORK_QAA_PREFIX))
+ return authData.getQAALevel().substring(PVPConstants.STORK_QAA_PREFIX.length());
+ else
+ return null;
+ }
+
+
+ private String geteIdentifier(PersonalAttribute personalAttribute) {
+ Logger.debug("Using base urn for identification value: " + authData.getIdentificationType() + " and target country: " + moastorkRequest.getStorkAuthnRequest().getSpCountry());
+ try {
+ return new BPKBuilder().buildStorkeIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(),
+ moastorkRequest.getStorkAuthnRequest().getSpCountry());
+ } catch (BuildException be) {
+ Logger.error("Stork eid could not be constructed; " + be.getMessage());
+ return null; // TODO error
+ }
+ }
+
+ private List<String> getECApplicationRole(PersonalAttribute personalAttribute) {
+ List<String> storkRoles = null;
+
+ if (authData.getAuthenticationRoles() != null
+ && authData.getAuthenticationRoles().size() > 0) {
+
+ storkRoles = new ArrayList<String>();
+ PVPtoSTORKMapper mapper = PVPtoSTORKMapper.getInstance();
+ for (AuthenticationRole el : authData.getAuthenticationRoles()) {
+ String storkRole = mapper.map(el);
+ if (MiscUtil.isNotEmpty(storkRole))
+ storkRoles.add(storkRole);
+ }
+ }
+ return storkRoles;
+ }
+
+ private String getFormatedDateOfBirth(PersonalAttribute personalAttribute) {
+ if (authData.getDateOfBirth() != null) {
+ DateFormat fmt = new SimpleDateFormat("yyyyMMdd");
+ return fmt.format(authData.getDateOfBirth());
+ }
+ else
+ return null;
+ }
+
+ private void populateAttributeWithMethod(Method method, Object object, PersonalAttributeList attributeList, String storkAttribute, PersonalAttribute requestedAttribute) {
+ try {
+ Object attributeValue;
+ if (storkAttributeSimpleMapping.containsValue(method.getName())) {
+ attributeValue = method.invoke(object, new Class[]{});
+ } else {
+ attributeValue = method.invoke(object, requestedAttribute);
+ }
+
+ PersonalAttribute newAttribute = new PersonalAttribute();
+ newAttribute.setName(storkAttribute);
+ newAttribute.setIsRequired(requestedAttribute.isRequired());
+
+ if (attributeValue != null) {
+ newAttribute.setStatus(AttributeStatusType.AVAILABLE.value());
+ Logger.info("Got attribute value: " + attributeValue);
+
+ if (attributeValue instanceof String)
+ newAttribute.setValue(new ArrayList<String>(Collections.singletonList((String)attributeValue)));
+
+ else if (attributeValue instanceof List<?>) {
+ List<?> attributeValueList = (List<?>) attributeValue;
+ if (attributeValueList.size() > 0 && attributeValueList.get(0) instanceof String) {
+ newAttribute.setValue((List<String>) attributeValueList);
+
+ } else {
+ Logger.info("Attribute " + storkAttribute + " is not available.");
+ newAttribute.setStatus(AttributeStatusType.NOT_AVAILABLE.value());
+
+ }
+
+ } else {
+ Logger.error("Receive an unsupported type for attribute " + storkAttribute);
+
+ }
+ attributeList.add(newAttribute);
+
+ } else {
+ Logger.info("Attribute " + storkAttribute + " is not available.");
+ newAttribute.setStatus(AttributeStatusType.NOT_AVAILABLE.value());
+ }
+
+ } catch (InvocationTargetException e) {
+ Logger.error("Invocation target exception while getting attribute: " + storkAttribute);
+ Logger.debug(e);
+ } catch (IllegalAccessException e) {
+ Logger.error("Illegal access exception while getting attribute: " + storkAttribute);
+ Logger.debug(e);
+ } catch (NullPointerException e) {
+ Logger.error("Could not find method: " + storkAttribute);
+ Logger.debug(e);
+ }
+ }
+
+
+}
+
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOASTORKRequest.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOASTORKRequest.java
new file mode 100644
index 000000000..11eb01453
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOASTORKRequest.java
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.opensaml.saml2.core.Attribute;
+
+import at.gv.egovernment.moa.id.auth.builder.DynamicOAAuthParameterBuilder;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.config.auth.data.DynamicOAAuthParameters;
+import at.gv.egovernment.moa.id.moduls.RequestImpl;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.protocols.pvp2x.builder.AttributQueryBuilder;
+import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.Constants;
+import eu.stork.peps.auth.commons.IPersonalAttributeList;
+import eu.stork.peps.auth.commons.STORKAttrQueryRequest;
+import eu.stork.peps.auth.commons.STORKAuthnRequest;
+import eu.stork.peps.auth.commons.STORKAuthnResponse;
+
+/**
+ * Implements MOA request and stores StorkAuthn/Attr-Request related data.
+ *
+ * @author bsuzic
+ */
+public class MOASTORKRequest extends RequestImpl {
+
+ public static final List<String> DEFAULTREQUESTEDATTRFORINTERFEDERATION = Arrays.asList(
+ new String[] {
+ PVPConstants.BPK_NAME,
+ PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME,
+ PVPConstants.GIVEN_NAME_NAME,
+ PVPConstants.PRINCIPAL_NAME_NAME,
+ PVPConstants.BIRTHDATE_NAME,
+ PVPConstants.EID_CITIZEN_QAA_LEVEL_NAME,
+ });
+
+ /** The Constant serialVersionUID. */
+ private static final long serialVersionUID = 4581953368724501376L;
+
+ /** The request id. */
+ private String requestID;
+
+ /** The stork authn request. */
+ private STORKAuthnRequest storkAuthnRequest;
+
+ /** The stork attr query request. */
+ private STORKAttrQueryRequest storkAttrQueryRequest;
+
+
+ /**
+ * Sets the sTORK authn request.
+ *
+ * @param request the new sTORK authn request
+ */
+ public void setSTORKAuthnRequest(STORKAuthnRequest request) {
+ this.storkAuthnRequest = request;
+ }
+
+ /**
+ * Sets the sTORK attr request.
+ *
+ * @param request the new sTORK attr request
+ */
+ public void setSTORKAttrRequest(STORKAttrQueryRequest request) {
+ this.storkAttrQueryRequest = request;
+ }
+
+ /**
+ * Checks if the container holds an AttrQueryRequest
+ *
+ * @return true, if is attr request
+ */
+ public boolean isAttrRequest() {
+ return null != storkAttrQueryRequest;
+ }
+
+ /**
+ * Checks if the container holds an AuthnRequest
+ *
+ * @return true, if is authn request
+ */
+ public boolean isAuthnRequest() {
+ return null != storkAuthnRequest;
+ }
+
+ /**
+ * Gets the stork authn request.
+ *
+ * @return the stork authn request
+ */
+ public STORKAuthnRequest getStorkAuthnRequest() {
+ return this.storkAuthnRequest;
+ }
+
+ /**
+ * Gets the stork attr query request.
+ *
+ * @return the stork attr query request
+ */
+ public STORKAttrQueryRequest getStorkAttrQueryRequest() {
+ return this.storkAttrQueryRequest;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#getOAURL()
+ */
+ public String getOAURL() {
+ if (isAuthnRequest())
+ return storkAuthnRequest.getAssertionConsumerServiceURL();
+ else if (isAttrRequest())
+ return storkAttrQueryRequest.getAssertionConsumerServiceURL();
+ else {
+ Logger.error("There is no authentication or attribute request contained in MOASTORKRequest.");
+ return null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#isPassiv()
+ */
+ public boolean isPassiv() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#forceAuth()
+ */
+ public boolean forceAuth() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#isSSOSupported()
+ */
+ public boolean isSSOSupported() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#setRequestID(java.lang.String)
+ */
+ public void setRequestID(String id) {
+ this.requestID = id;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#getRequestID()
+ */
+ public String getRequestID() {
+ return this.requestID;
+ }
+
+ /**
+ * Gets the personal attribute list.
+ *
+ * @return the personal attribute list
+ */
+ public IPersonalAttributeList getPersonalAttributeList() {
+ if(isAttrRequest())
+ return this.storkAttrQueryRequest.getPersonalAttributeList();
+ else
+ return this.storkAuthnRequest.getPersonalAttributeList();
+ }
+
+ /**
+ * Gets the sp country.
+ *
+ * @return the sp country
+ */
+ public String getSpCountry() {
+ if(isAttrRequest())
+ return this.storkAttrQueryRequest.getSpCountry();
+ else
+ return this.storkAuthnRequest.getSpCountry();
+ }
+
+ /**
+ * Gets the assertion consumer service url.
+ *
+ * @return the assertion consumer service url
+ */
+ public String getAssertionConsumerServiceURL() {
+ if(isAttrRequest())
+ return this.storkAttrQueryRequest.getAssertionConsumerServiceURL();
+ else
+ return this.storkAuthnRequest.getAssertionConsumerServiceURL();
+ }
+
+ /**
+ * Gets the citizen country code.
+ *
+ * @return the citizen country code
+ */
+ public String getCitizenCountryCode() {
+ if(isAttrRequest())
+ return this.storkAttrQueryRequest.getCitizenCountryCode();
+ else
+ return this.storkAuthnRequest.getCitizenCountryCode();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.RequestImpl#getRequestedAttributes()
+ */
+ @Override
+ public List<Attribute> getRequestedAttributes() {
+ //TODO: only for testing with MOA-ID as PVP Stammportal
+ IOAAuthParameters oa;
+ try {
+ oa = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(getOAURL());
+ oa = DynamicOAAuthParameterBuilder.buildFromAuthnRequest(oa, this);
+
+ DynamicOAAuthParameters tmp = (DynamicOAAuthParameters) oa;
+ tmp.setBusinessTarget(Constants.URN_PREFIX_CDID + "+BF");
+
+ return AttributQueryBuilder.buildSAML2AttributeList(tmp, DEFAULTREQUESTEDATTRFORINTERFEDERATION.iterator());
+
+ } catch (ConfigurationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+
+ //return new ArrayList<Attribute>();
+
+ }
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOASTORKResponse.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOASTORKResponse.java
new file mode 100644
index 000000000..d2cf2e813
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOASTORKResponse.java
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.moduls.RequestImpl;
+import at.gv.egovernment.moa.logging.Logger;
+import eu.stork.peps.auth.commons.IPersonalAttributeList;
+import eu.stork.peps.auth.commons.PersonalAttributeList;
+import eu.stork.peps.auth.commons.STORKAttrQueryResponse;
+import eu.stork.peps.auth.commons.STORKAuthnResponse;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.opensaml.saml2.core.Attribute;
+
+/**
+ * Implements MOA request and stores StorkAuthn/Attr-Request related data.
+ *
+ * @author bsuzic
+ */
+public class MOASTORKResponse extends RequestImpl {
+
+ /**
+ * The Constant serialVersionUID.
+ */
+ private static final long serialVersionUID = -5798803155055518747L;
+
+ /**
+ * The stork authn request.
+ */
+ private STORKAuthnResponse storkAuthnResponse;
+
+ /**
+ * The stork attr query request.
+ */
+ private STORKAttrQueryResponse storkAttrQueryResponse;
+
+ /**
+ * The action.
+ */
+ String action = null;
+
+ /**
+ * The token
+ */
+ private byte[] storkAuthnResponseToken = null;
+
+ /**
+ * The request id.
+ */
+ private String requestID;
+
+
+ /**
+ * The module.
+ */
+ String module = null;
+
+ /**
+ * The target.
+ */
+ private String target = null;
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#requestedModule()
+ */
+ public String requestedModule() {
+ return this.module;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#requestedAction()
+ */
+ public String requestedAction() {
+ return action;
+ }
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#getRequestID()
+ */
+ public String getRequestID() {
+ return this.requestID;
+ }
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#getTarget()
+ */
+ public String getTarget() {
+ return this.target;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#isSSOSupported()
+ */
+ public boolean isSSOSupported() {
+ return false;
+ }
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#forceAuth()
+ */
+ public boolean forceAuth() {
+ return false;
+ }
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#setModule(java.lang.String)
+ */
+ public void setModule(String module) {
+ this.module = module;
+ }
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#setRequestID(java.lang.String)
+ */
+ public void setRequestID(String id) {
+ this.requestID = id;
+ }
+
+ /**
+ * Sets the sTORK authn response.
+ *
+ * @param request the new sTORK authn response
+ */
+ public void setSTORKAuthnResponse(STORKAuthnResponse request) {
+ this.storkAuthnResponse = request;
+ }
+
+ /**
+ * Sets the sTORK authn response token
+ *
+ * @param request the new sTORK authn response token
+ */
+ public void setSTORKAuthnResponseToken(byte[] token) {
+ this.storkAuthnResponseToken = token;
+ }
+
+ /**
+ * Gets the sTORK authn response token .
+ *
+ * @param request the new sTORK authn response
+ */
+ public byte[] getSTORKAuthnResponseToken() {
+ return this.storkAuthnResponseToken;
+ }
+ /**
+ * Sets the sTORK attr response.
+ *
+ * @param request the new sTORK attr response
+ */
+ public void setSTORKAttrResponse(STORKAttrQueryResponse request) {
+ this.storkAttrQueryResponse = request;
+ }
+
+ /**
+ * Checks if the container holds an AttrQuery
+ *
+ * @return true, if is attr response
+ */
+ public boolean isAttrResponse() {
+ return null != storkAttrQueryResponse;
+ }
+
+ /**
+ * Checks if the container holds an AuthnRequest
+ *
+ * @return true, if is authn response
+ */
+ public boolean isAuthnResponse() {
+ return null != storkAuthnResponse;
+ }
+
+
+ /**
+ * Gets the AuthnResponse.
+ *
+ * @return the stork authn response
+ */
+ public STORKAuthnResponse getStorkAuthnResponse() {
+ return this.storkAuthnResponse;
+ }
+
+ /**
+ * Gets the AttrQueryResponse.
+ *
+ * @return the stork attr query response
+ */
+ public STORKAttrQueryResponse getStorkAttrQueryResponse() {
+ return this.storkAttrQueryResponse;
+ }
+
+ /**
+ * Gets the personal attribute list.
+ *
+ * @return the personal attribute list
+ */
+ public IPersonalAttributeList getPersonalAttributeList() {
+ if (isAttrResponse())
+ return this.storkAttrQueryResponse.getPersonalAttributeList();
+ else
+ return this.storkAuthnResponse.getPersonalAttributeList();
+ }
+
+ /**
+ * Sets the personal attribute list.
+ *
+ * @param populateAttributes the new personal attribute list
+ */
+ public void setPersonalAttributeList(PersonalAttributeList populateAttributes) {
+ if (isAttrResponse())
+ this.storkAttrQueryResponse.setPersonalAttributeList(populateAttributes);
+ else
+ this.storkAuthnResponse.setPersonalAttributeList(populateAttributes);
+ }
+
+ /**
+ * Sets the country.
+ *
+ * @param spCountry the new country
+ */
+ public void setCountry(String spCountry) {
+ if (isAttrResponse())
+ this.storkAttrQueryResponse.setCountry(spCountry);
+ else
+ this.storkAuthnResponse.setCountry(spCountry);
+ }
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#getOAURL()
+ */
+ public String getOAURL() {
+ if (isAuthnResponse())
+ return storkAuthnResponse.getAudienceRestriction();
+ else if (isAttrResponse())
+ return storkAttrQueryResponse.getAudienceRestriction();
+ else {
+ Logger.error("There is no authentication or attribute request contained in MOASTORKRequest.");
+ return null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#isPassiv()
+ */
+ public boolean isPassiv() {
+ return false;
+ }
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IRequest#setAction(java.lang.String)
+ */
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.RequestImpl#getRequestedAttributes()
+ */
+ @Override
+ public List<Attribute> getRequestedAttributes() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java
new file mode 100644
index 000000000..a3fac0f6e
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.logging.Logger;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+/**
+ * @author bsuzic
+ * Date: 5/5/14, Time: 2:35 PM
+ */
+public abstract class MandateContainer {
+ protected String mandateIssuePlace = null;
+ protected String mandateIssueDate = null;
+ protected String mandateIssueTime = null;
+ protected String simpleMandateContent = null;
+ protected String mandateValidFrom = null;
+ protected String mandateValidTo = null;
+ protected String annotation = null;
+ protected String physicalRepresentativeIdentificationValue = null;
+ protected String physicalRepresentativeIdentificationType = null;
+ protected String physicalRepresentativeGivenName = null;
+ protected String physicalRepresentativeFamilyName = null;
+ protected String physicalRepresentativeBirthDate = null;
+ protected XPath xPath = null;
+
+
+ public MandateContainer(String mandate) throws XPathExpressionException, MOAIDException {
+ Logger.debug("Received mandate content for processing: " + mandate);
+
+ xPath = XPathFactory.newInstance().newXPath();
+ HashMap<String, String> prefMap = new HashMap<String, String>() {{
+ put(S2Constants.MANDATE_PREFIX, S2Constants.MANDATE_NS);
+ put(S2Constants.PERSONDATA_PREFIX, S2Constants.PERSONDATA_NS);
+ put(S2Constants.XMLDSIG_PREFIX, S2Constants.XMLDSIG_NS);
+ }};
+
+ SimpleNamespaceContext namespace = new SimpleNamespaceContext(prefMap);
+ xPath.setNamespaceContext(namespace);
+ }
+
+
+ public void validateMandateStructure(String localMethods[]) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, MOAIDException {
+ for (String localMethod : localMethods) {
+ Method method = this.getClass().getMethod(localMethod);
+ Object x = method.invoke(this);
+ if ((x == null) || x.toString().length() == 0) {
+ throw new MOAIDException("stork.16", new Object[] {localMethod}); // TODO
+ }
+ }
+ Logger.debug("Mandate structure validated");
+ }
+
+
+ public String getMandateIssuePlace() {
+ return mandateIssuePlace;
+ }
+
+ public void setMandateIssuePlace(String mandateIssuePlace) {
+ this.mandateIssuePlace = mandateIssuePlace;
+ }
+
+ public String getMandateIssueDate() {
+ return mandateIssueDate;
+ }
+
+ public void setMandateIssueDate(String mandateIssueDate) {
+ this.mandateIssueDate = mandateIssueDate;
+ }
+
+ public String getMandateIssueTime() {
+ return mandateIssueTime;
+ }
+
+ public void setMandateIssueTime(String mandateIssueTime) {
+ this.mandateIssueTime = mandateIssueTime;
+ }
+
+ public String getSimpleMandateContent() {
+ return simpleMandateContent;
+ }
+
+ public void setSimpleMandateContent(String simpleMandateContent) {
+ this.simpleMandateContent = simpleMandateContent;
+ }
+
+ public String getMandateValidFrom() {
+ return mandateValidFrom;
+ }
+
+ public void setMandateValidFrom(String mandateValidFrom) {
+ this.mandateValidFrom = mandateValidFrom;
+ }
+
+ public String getMandateValidTo() {
+ return mandateValidTo;
+ }
+
+ public void setMandateValidTo(String mandateValidTo) {
+ this.mandateValidTo = mandateValidTo;
+ }
+
+ public String getPhysicalRepresentativeIdentificationValue() {
+ return physicalRepresentativeIdentificationValue;
+ }
+
+ public void setPhysicalRepresentativeIdentificationValue(String physicalRepresentativeIdentificationValue) {
+ this.physicalRepresentativeIdentificationValue = physicalRepresentativeIdentificationValue;
+ }
+
+ public String getPhysicalRepresentativeIdentificationType() {
+ return physicalRepresentativeIdentificationType;
+ }
+
+ public void setPhysicalRepresentativeIdentificationType(String physicalRepresentativeIdentificationType) {
+ this.physicalRepresentativeIdentificationType = physicalRepresentativeIdentificationType;
+ }
+
+ public String getPhysicalRepresentativeGivenName() {
+ return physicalRepresentativeGivenName;
+ }
+
+ public void setPhysicalRepresentativeGivenName(String physicalRepresentativeGivenName) {
+ this.physicalRepresentativeGivenName = physicalRepresentativeGivenName;
+ }
+
+ public String getPhysicalRepresentativeFamilyName() {
+ return physicalRepresentativeFamilyName;
+ }
+
+ public void setPhysicalRepresentativeFamilyName(String physicalRepresentativeFamilyName) {
+ this.physicalRepresentativeFamilyName = physicalRepresentativeFamilyName;
+ }
+
+ public String getPhysicalRepresentativeBirthDate() {
+ return physicalRepresentativeBirthDate;
+ }
+
+ public void setPhysicalRepresentativeBirthDate(String physicalRepresentativeBirthDate) {
+ // making it conform to STORK dateOfBirth specifications, removing dash
+ this.physicalRepresentativeBirthDate = physicalRepresentativeBirthDate.replaceAll("-","");
+ }
+
+ public String getAnnotation() {
+ return annotation;
+ }
+
+ public void setAnnotation(String annotation) {
+ this.annotation = annotation;
+ }
+
+
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java
new file mode 100644
index 000000000..e58fe804f
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java
@@ -0,0 +1,602 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import at.gv.egovernment.moa.id.auth.builder.BPKBuilder;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.auth.exception.BuildException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.SLOInformationInterface;
+import at.gv.egovernment.moa.id.moduls.IAction;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.Constants;
+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.auth.commons.STORKAttrQueryResponse;
+import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.*;
+import org.apache.commons.codec.binary.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Marshaller;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.regex.Pattern;
+
+/**
+ * Entry point for mandate retrieval. Processes MIS data and transforms into STORK mandate attribute.
+ * Additionally provides eIdentifier attribute (if requested) in order to enable identity correlation
+ */
+public class MandateRetrievalRequest implements IAction {
+
+ private IAuthData authData;
+ private MOASTORKRequest moaStorkRequest;
+ private IdentityLink representingIdentityLink;
+ private Integer QAALevel;
+ private byte[] originalContent;
+
+ public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException {
+ Logger.debug("Entering AttributeRequest for MandateProvider");
+ httpResp.reset();
+ this.representingIdentityLink = authData.getIdentityLink();
+ this.QAALevel = translateQAALevel(authData.getQAALevel());
+
+ // preparing original content and removing sensitive data from it
+ try {
+ this.originalContent = authData.getMISMandate().getMandate();
+ } catch (Exception e) {
+ Logger.error("Could not extract mandate");
+ Logger.debug(e);
+ throw new MOAIDException("stork.26", new Object[]{});
+ }
+ String originalMandate = StringUtils.newStringUtf8(authData.getMISMandate().getMandate()).replaceAll("<pd:Value>.*?==</pd:Value><pd:Type>urn:publicid:gv.at:baseid</pd:Type>","<pd:Value></pd:Value><pd:Type></pd:Type>");;
+ Logger.debug("Removing personal identification value and type from original mandate ");
+ originalContent = StringUtils.getBytesUtf8(originalMandate);
+
+ OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(req.getOAURL());
+ if (oaParam == null)
+ throw new AuthenticationException("stork.12", new Object[]{req.getOAURL()});
+
+ MOASTORKResponse moaStorkResponse = new MOASTORKResponse();
+ STORKAttrQueryResponse attrResponse = new STORKAttrQueryResponse();
+
+ this.authData = authData;
+
+ if ((req instanceof MOASTORKRequest)) {
+ this.moaStorkRequest = (MOASTORKRequest) req;
+ } else {
+ Logger.error("Internal error - did not receive MOASTORKRequest as expected");
+ throw new MOAIDException("stork.27", new Object[]{});
+ }
+
+
+ if (!(moaStorkRequest.isAttrRequest() || moaStorkRequest.getStorkAttrQueryRequest() == null)) {
+ Logger.error("Did not receive attribute request as expected");
+ throw new MOAIDException("stork.27", new Object[]{});
+ }
+
+ MandateContainer mandateContainer = null;
+
+ try {
+ mandateContainer = new CorporateBodyMandateContainer(new String(authData.getMISMandate().getMandate(), "UTF-8"));
+ } catch (Exception ex) {
+ try {
+ mandateContainer = new PhyPersonMandateContainer(new String(authData.getMISMandate().getMandate(), "UTF-8"));
+ } catch (Exception ex2) {
+ Logger.error("Could not extract data and create mandate container.");
+ throw new MOAIDException("stork.27", new Object[]{});
+ }
+ }
+
+ IPersonalAttributeList sourceAttributeList = moaStorkRequest.getStorkAttrQueryRequest().getPersonalAttributeList();
+
+ IPersonalAttributeList attributeList = new PersonalAttributeList();
+
+ // according to new mapping, only mandate attribute is directly relevant
+ for (PersonalAttribute currentAttribute : sourceAttributeList) {
+ Logger.debug("Evaluating attributes, current attribute: " + currentAttribute.getName());
+ if (currentAttribute.getName().equals("mandateContent")) { // deprecated
+ MandateContentType mandateContent = getMandateContent(mandateContainer, currentAttribute);
+ attributeList.add(marshallComplexAttribute(currentAttribute, mandateContent));
+ } else if (currentAttribute.getName().equals("representative")) { // deprecated
+ RepresentationPersonType representative = getRepresentative(mandateContainer, currentAttribute);
+ attributeList.add(marshallComplexAttribute(currentAttribute, representative));
+ } else if (currentAttribute.getName().equals("represented")) {
+ RepresentationPersonType represented = getRepresented(mandateContainer, currentAttribute);
+ attributeList.add(marshallComplexAttribute(currentAttribute, represented));
+ } else if (currentAttribute.getName().equals("mandate")) {
+ MandateType mandateType = getMandateType(mandateContainer, currentAttribute);
+ attributeList.add(marshallComplexAttribute(currentAttribute, mandateType));
+ } else if (currentAttribute.getName().equals("legalName")) {
+ String legalName = getLegalName(mandateContainer, currentAttribute);
+ if (legalName.length() > 0) {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(legalName), AttributeStatusType.AVAILABLE.value()));
+ } else {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(legalName), AttributeStatusType.NOT_AVAILABLE.value()));
+ }
+ } else if (currentAttribute.getName().equals("eLPIdentifier")) {
+ String eLPIdentifier = geteLPIdentifier(mandateContainer, currentAttribute);
+ if (eLPIdentifier.length() > 0) {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(eLPIdentifier), AttributeStatusType.AVAILABLE.value()));
+ } else {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(eLPIdentifier), AttributeStatusType.NOT_AVAILABLE.value()));
+ }
+ } else if (currentAttribute.getName().equals("type")) {
+ String type = getCompanyType(mandateContainer, currentAttribute);
+ if (type.length() > 0) {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(type), AttributeStatusType.AVAILABLE.value()));
+ } else {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(type), AttributeStatusType.NOT_AVAILABLE.value()));
+ }
+ } else if (currentAttribute.getName().equals("status")) {
+ String status = getCompanyStatus(mandateContainer, currentAttribute);
+ if (status.length() > 0) {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(status), AttributeStatusType.AVAILABLE.value()));
+ } else {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(status), AttributeStatusType.NOT_AVAILABLE.value()));
+ }
+ } else if (currentAttribute.getName().equals("translatableType")) {
+ String translatableType = getCompanyTranslatableType(mandateContainer, currentAttribute);
+ if (translatableType.length() > 0) {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(translatableType), AttributeStatusType.AVAILABLE.value()));
+ } else {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(translatableType), AttributeStatusType.NOT_AVAILABLE.value()));
+ }
+ }
+
+ if (currentAttribute.getName().equals("eIdentifier")) {
+ attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(geteIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(), moaStorkRequest.getStorkAttrQueryRequest().getSpCountry())), AttributeStatusType.AVAILABLE.value()));
+ Logger.info("Adding eIdentifier for mandate holder using SP country: " + moaStorkRequest.getStorkAttrQueryRequest().getSpCountry());
+ }
+
+ }
+
+
+// if (attrResponse.getPersonalAttributeList().size() == 0) {
+// Logger.error("AttributeList empty - could not retrieve attributes");
+// throw new MOAIDException("stork.16", new Object[]{}); // TODO MESSAGE
+// }
+
+ attrResponse.setPersonalAttributeList(attributeList);
+ moaStorkResponse.setSTORKAttrResponse(attrResponse);
+
+ Logger.debug("Attributes retrieved: " + moaStorkResponse.getStorkAttrQueryResponse().getPersonalAttributeList().size() + " for SP country " + attrResponse.getCountry());
+
+ // Prepare extended attributes
+ Logger.debug("Preparing data container");
+
+ // create fresh container
+ DataContainer container = new DataContainer();
+
+ // - fill in the request we extracted above
+ container.setRequest(moaStorkRequest);
+
+ // - fill in the partial response created above
+ container.setResponse(moaStorkResponse);
+
+ container.setRemoteAddress(httpReq.getRemoteAddr());
+
+ Logger.debug("Data container prepared");
+
+ // ask for consent if necessary
+ if (oaParam.isRequireConsentForStorkAttributes())
+ new ConsentEvaluator().requestConsent(container, httpReq, httpResp, authData, oaParam);
+ else
+ new ConsentEvaluator().generateSTORKResponse(httpResp, container);
+
+ return null;
+ }
+
+ private Integer translateQAALevel(String qaaLevel) throws MOAIDException {
+ if (qaaLevel.equals(PVPConstants.STORK_QAA_1_1))
+ return 1;
+ if (qaaLevel.equals(PVPConstants.STORK_QAA_1_2))
+ return 2;
+ if (qaaLevel.equals(PVPConstants.STORK_QAA_1_3))
+ return 3;
+ if (qaaLevel.equals(PVPConstants.STORK_QAA_1_4))
+ return 4;
+ Logger.error("Wrong QAA Number format");
+ throw new MOAIDException("stork.28", new Object[]{});
+ }
+
+ private String geteLPIdentifier(MandateContainer mandateContainer, PersonalAttribute currentAttribute) throws MOAIDException {
+ RepresentationPersonType represented = getRepresented(mandateContainer, currentAttribute);
+ if (mandateContainer instanceof CorporateBodyMandateContainer) {
+ return represented.getELPIdentifier();
+ } else if (currentAttribute.isRequired()) {
+ Logger.error("Cannot provide eLPIdentifier for natural person.");
+ throw new MOAIDException("stork.29", new Object[]{currentAttribute.getName()});
+ }
+ return "";
+ }
+
+ private String geteIdentifier(String identificationType, String identificationValue, String destinationCountry) throws MOAIDException {
+ BPKBuilder bpkBuilder = new BPKBuilder();
+ try {
+ return bpkBuilder.buildStorkeIdentifier(identificationType, identificationValue, destinationCountry);
+ } catch (BuildException be) {
+ Logger.error("Could not build STORK eIdentifier while generating mandate assertion.");
+ throw new MOAIDException("stork.29", new Object[]{});
+ }
+ }
+
+ private PersonalAttribute marshallComplexAttribute(PersonalAttribute currentAttribute, Object obj) { // TODO refactor
+ StringWriter stringWriter = new StringWriter();
+ try {
+ if (obj instanceof MandateContentType) {
+ final Marshaller marshaller = JAXBContext.newInstance(MandateContentType.class).createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ marshaller.marshal(new JAXBElement<MandateContentType>(new QName("urn:eu:stork:names:tc:STORK:1.0:assertion", currentAttribute.getName()), MandateContentType.class, null, (MandateContentType) obj), stringWriter);
+ } else if (obj instanceof MandateType) {
+ final Marshaller marshaller = JAXBContext.newInstance(MandateType.class).createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ marshaller.marshal(new JAXBElement<MandateType>(new QName("urn:eu:stork:names:tc:STORK:1.0:assertion", currentAttribute.getName()), MandateType.class, null, (MandateType) obj), stringWriter);
+ } else if (obj instanceof RepresentationPersonType) {
+ final Marshaller marshaller = JAXBContext.newInstance(RepresentationPersonType.class).createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ marshaller.marshal(new JAXBElement<RepresentationPersonType>(new QName("urn:eu:stork:names:tc:STORK:1.0:assertion", currentAttribute.getName()), RepresentationPersonType.class, null, (RepresentationPersonType) obj), stringWriter);
+ }
+
+ } catch (Exception ex) {
+ Logger.error("Could not marshall atrribute: " + currentAttribute.getName() + ", " + ex.getMessage());
+ return new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), new ArrayList<String>(), AttributeStatusType.NOT_AVAILABLE.value());
+ }
+ ArrayList<String> value = new ArrayList<String>();
+ value.add(stringWriter.toString());
+
+ PersonalAttribute personalAttribute = new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), value, AttributeStatusType.AVAILABLE.value());
+ return personalAttribute;
+ }
+
+
+ private String mapPowersType(MandateContainer mandateContainer) {
+ Logger.debug("Analyzing mandate of type: " + mandateContainer.getAnnotation() + ".");
+ // using if for java 6 compatibility if necessary
+ if (mandateContainer.getAnnotation().equals("ELGABilateral")) {
+ return "6"; // Health Powers
+ } else if (mandateContainer.getAnnotation().equals("ERsB")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("Gesetzliche Vollmacht auf Basis Ergäzungsregister für sonstige Betroffene")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("Gesetzliche Vollmacht auf Basis Ergänzungsregister für sonstige Betroffene")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().contains("Gesetzliche Vollmacht auf Basis Erg")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("GeneralvollmachtBilateral")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().contains("Gesetzliche Vollmacht auf Basis Firmenbuch")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("ERsBMitPostvollmacht")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("ZVR")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("ZVRMitPostvollmacht")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("EVB")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("Einzelvertretungsbefugnis")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("Prokura")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("Notar")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("Organwalter")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("Rechtsanwalt")) {
+ return "0"; // General Powers
+ } else if (mandateContainer.getAnnotation().equals("Ziviltechniker")) {
+ return "0"; // General Powers
+ }
+ Logger.debug("Returning other type of mandate");
+ return "9";
+ }
+
+ private MandateType getMandateType(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException {
+ MandateType mandateType = new MandateType();
+ RepresentationPersonType representative = getRepresentative(mandateContainer, sourceAttribute);
+ RepresentationPersonType represented = getRepresented(mandateContainer, sourceAttribute);
+ MandateContentType mandateContent = getMandateContent(mandateContainer, sourceAttribute);
+ mandateType.setRepresentative(representative);
+ mandateType.setRepresented(represented);
+ mandateType.getMandateContent().add(mandateContent);
+ Logger.debug("Complex attribute extracted: " + sourceAttribute.getName());
+ return mandateType;
+ }
+
+ private String getLegalName(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException {
+ RepresentationPersonType represented = getRepresented(mandateContainer, sourceAttribute);
+ if (mandateContainer instanceof CorporateBodyMandateContainer) {
+ represented.getLegalName();
+ //return represented.getName();
+ } else if (sourceAttribute.isRequired()) {
+ Logger.error("Cannot provide legalName for natural person.");
+ throw new MOAIDException("stork.19", new Object[]{sourceAttribute.getName()});
+ }
+ return "";
+ }
+
+
+ private String getLegalIdentificationType(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException {
+ if (mandateContainer instanceof CorporateBodyMandateContainer) {
+ return ((CorporateBodyMandateContainer) mandateContainer).getCorpMandatorIdentificationType();
+ } else if (sourceAttribute.isRequired()) {
+ Logger.error("Cannot provide type for natural person.");
+ throw new MOAIDException("stork.19", new Object[]{sourceAttribute.getName()}); // TODO
+ }
+ return "";
+ }
+
+ private String getCompanyStatus(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException {
+ String legalName = getLegalName(mandateContainer, sourceAttribute);
+ if (legalName.contains("in Liquidation") || legalName.contains("in Liqu.")) {
+ return "L"; // liqudation
+ }
+ return "R";
+ }
+
+ private String getCompanyType(String legalName, String legalIdentificationType, PersonalAttribute sourceAttrivbute) throws MOAIDException {
+ // compile patterns for different organisation types
+ // sources: USP, WKO, LexAndTax
+
+ // gmbh patterns
+ ArrayList<Pattern> gmbhPatterns = new ArrayList<Pattern>();
+ gmbhPatterns.add(Pattern.compile(".+ GmbH(( in Liquidation)|( in Liqu.)){0,1}$"));
+ gmbhPatterns.add(Pattern.compile(".+ GesmbH$"));
+ gmbhPatterns.add(Pattern.compile(".+ Gesellschaft mit beschränkter Haftung$"));
+ gmbhPatterns.add(Pattern.compile(".+ Ges\\.m\\.b\\.H\\.$"));
+ gmbhPatterns.add(Pattern.compile(".+ G\\.m\\.b\\.H\\.$"));
+ gmbhPatterns.add(Pattern.compile(".+ Handelsges\\.m\\.b\\.H\\.$"));
+ gmbhPatterns.add(Pattern.compile(".+ Gesellschaft m\\.b\\.H\\.$"));
+
+ // ag patterns
+ ArrayList<Pattern> agPatterns = new ArrayList<Pattern>();
+ agPatterns.add(Pattern.compile(".+ AG$"));
+ agPatterns.add(Pattern.compile(".+ Aktiengesellschaft$"));
+
+ // og patterns
+ ArrayList<Pattern> ogPatterns = new ArrayList<Pattern>();
+ ogPatterns.add(Pattern.compile(".+ OG$"));
+ ogPatterns.add(Pattern.compile(".+ OHG$"));
+ ogPatterns.add(Pattern.compile(".+ offene Gesellschaft$"));
+
+ // kg patterns
+ ArrayList<Pattern> kgPatterns = new ArrayList<Pattern>();
+ kgPatterns.add(Pattern.compile(".+ KG$"));
+ kgPatterns.add(Pattern.compile(".+ Kommanditgesellschaft$"));
+
+ // eu patterns
+ ArrayList<Pattern> euPatterns = new ArrayList<Pattern>();
+ euPatterns.add(Pattern.compile(".+ eingetragene Unternehmerin$"));
+ euPatterns.add(Pattern.compile(".+ eingetragener Unternehmer$"));
+ euPatterns.add(Pattern.compile(".+ e\\.U\\.$"));
+
+
+ // company patterns
+ HashMap<String, ArrayList<Pattern>> companyPatterns = new HashMap<String, ArrayList<Pattern>>();
+ companyPatterns.put("GmbH", gmbhPatterns);
+ companyPatterns.put("AG", agPatterns);
+ companyPatterns.put("OG", ogPatterns);
+ companyPatterns.put("KG", kgPatterns);
+ companyPatterns.put("e.U.", euPatterns);
+
+ // iterate over different types of companies and check if the name ending matches
+ if (S2Constants.IDENTIFICATION_TYPE_COMPANY.equals(legalIdentificationType)) {
+ for (String companyType : companyPatterns.keySet()) {
+ for (Pattern pattern : companyPatterns.get(companyType)) {
+ if (pattern.matcher(legalName).matches()) {
+ return companyType;
+ }
+ }
+ }
+ }
+
+ // check if the subject is association
+ if (S2Constants.IDENTIFICATION_TYPE_ASSOCIATION.equals(legalIdentificationType)) {
+ return "Verein";
+ }
+
+ // check if the subject falls under category of others
+ if (S2Constants.IDENTIFICATION_TYPE_OTHERS.equals(legalIdentificationType)) {
+ return "ERsB";
+ }
+
+ return "";
+ }
+
+ private String getCompanyType(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException {
+ // retrieve the registered subject name and identification type
+ String legalName = getLegalName(mandateContainer, sourceAttribute);
+ String legalIdentificationType = getLegalIdentificationType(mandateContainer, sourceAttribute);
+ return getCompanyType(legalName, legalIdentificationType, sourceAttribute);
+ }
+
+ private String getCompanyTranslatableType(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException {
+ // retrieve first the company type
+ String companyType = getCompanyType(mandateContainer, sourceAttribute);
+
+ // translate company type based on the section 5.6 in STORK 2 D4.11
+ if (companyType.length() == 0) {
+ return "";
+ } else if (companyType.equals("GmbH")) {
+ return "G";
+ } else if (companyType.equals("AG")) {
+ return "A";
+ } else if (companyType.equals("OG")) {
+ return "O";
+ } else if (companyType.equals("KG")) {
+ return "K";
+ } else {
+ return "";
+ }
+ }
+
+
+ private String getRepresentedStorkeIdentifier(MandateContainer mandateContainer) throws MOAIDException {
+
+ if (!(mandateContainer instanceof PhyPersonMandateContainer)) {
+ Logger.error("Physical person mandate container missing");
+ throw new MOAIDException("stork.20", new Object[]{}); // TODO
+ }
+
+ PhyPersonMandateContainer phyPersonMandateContainer = (PhyPersonMandateContainer) mandateContainer;
+
+ if (!phyPersonMandateContainer.getPhyPersMandatorIdentificationType().equals(Constants.URN_PREFIX_BASEID)) {
+ Logger.error("Identification type of represented person from MIS is not correct");
+ throw new MOAIDException("stork.20", new Object[]{}); // TODO
+ }
+
+ if (phyPersonMandateContainer.getPhyPersMandatorIdentificationValue().length() != 24) {
+ Logger.error("Identification value of represented person from MIS is not correct");
+ throw new MOAIDException("stork.20", new Object[]{}); // TODO
+ }
+
+ if ((this.moaStorkRequest.getStorkAttrQueryRequest().getSpCountry() == null) || (this.moaStorkRequest.getStorkAttrQueryRequest().getSpCountry().length() == 0)) {
+ Logger.error("Error accessing SP country code");
+ throw new MOAIDException("stork.20", new Object[]{}); // TODO
+ }
+
+ return geteIdentifier(phyPersonMandateContainer.getPhyPersMandatorIdentificationType(), phyPersonMandateContainer.getPhyPersMandatorIdentificationValue(), this.moaStorkRequest.getStorkAttrQueryRequest().getSpCountry());
+ }
+
+ private String getRepresentingStorkeIdentifier(MandateContainer mandateContainer) throws MOAIDException {
+ if ((this.representingIdentityLink == null)) {
+ Logger.error("Error accessing identityLink while fetching mandate attribute");
+ throw new MOAIDException("stork.20", new Object[]{}); // TODO
+ }
+
+ if ((this.moaStorkRequest.getStorkAttrQueryRequest().getSpCountry() == null) || (this.moaStorkRequest.getStorkAttrQueryRequest().getSpCountry().length() == 0)) {
+ Logger.error("Error accessing SP country code");
+ throw new MOAIDException("stork.20", new Object[]{}); // TODO
+ }
+
+ if (!this.representingIdentityLink.getIdentificationType().equals(Constants.URN_PREFIX_BASEID)) {
+ Logger.error("Incorrect identity link (local): identification type is not correct! Got: " + this.representingIdentityLink.getIdentificationType());
+ throw new MOAIDException("stork.20", new Object[]{}); // TODO
+ }
+
+ if (!mandateContainer.getPhysicalRepresentativeIdentificationType().equals(Constants.URN_PREFIX_BASEID)) {
+ Logger.error("Incorrect identity link (MIS): identification type is not correct! Got: " + this.representingIdentityLink.getIdentificationType() + " (representingIdentityLink) and " + mandateContainer.getPhysicalRepresentativeIdentificationType() + " (mandateContainer.phyRepresentative)");
+ Logger.debug("mandatecontainervalue: " + mandateContainer.getPhysicalRepresentativeIdentificationValue() + ", representingidentitylinkvalue: " + this.representingIdentityLink.getIdentificationValue());
+ throw new MOAIDException("stork.20", new Object[]{}); // TODO
+ }
+
+ if (!mandateContainer.getPhysicalRepresentativeIdentificationValue().equals(this.representingIdentityLink.getIdentificationValue())) {
+ Logger.error("Identification values from MIS and local service are not equal!");
+ throw new MOAIDException("stork.20", new Object[]{}); // TODO
+ }
+
+ BPKBuilder bpkBuilder = new BPKBuilder();
+ try {
+ return bpkBuilder.buildStorkeIdentifier(this.representingIdentityLink, this.moaStorkRequest.getStorkAttrQueryRequest().getSpCountry());
+ } catch (BuildException be) {
+ Logger.error("Could not build STORK eIdentifier while generating mandate assertion.");
+ throw new MOAIDException("stork.20", new Object[]{}); // TODO
+ }
+
+ }
+
+ private RepresentationPersonType getRepresentative(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException {
+ RepresentationPersonType representative = new RepresentationPersonType();
+
+ representative.setEIdentifier(getRepresentingStorkeIdentifier(mandateContainer));
+ representative.setGivenName(mandateContainer.getPhysicalRepresentativeGivenName());
+ representative.setSurname(mandateContainer.getPhysicalRepresentativeFamilyName());
+ representative.setDateOfBirth(mandateContainer.getPhysicalRepresentativeBirthDate());
+
+ Logger.debug("Complex attribute extracted: " + sourceAttribute.getName());
+ return representative;
+ }
+
+ private RepresentationPersonType getRepresented(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException {
+ RepresentationPersonType represented = new RepresentationPersonType();
+
+ if (mandateContainer instanceof CorporateBodyMandateContainer) {
+ CorporateBodyMandateContainer corporateBodyMandateContainer = (CorporateBodyMandateContainer) mandateContainer;
+ represented.setELPIdentifier(corporateBodyMandateContainer.getCorpMandatorIdentificationValue());
+ represented.setLegalName(corporateBodyMandateContainer.getCorpMandatorFullName());
+ represented.setTextRegisteredAddress(null);
+ represented.setCanonicalRegisteredAddress(new CanonicalAddressType());
+ represented.setLegalForm(getCompanyType(corporateBodyMandateContainer.corpMandatorFullName, corporateBodyMandateContainer.corpMandatorIdentificationType, sourceAttribute));
+ } else if (mandateContainer instanceof PhyPersonMandateContainer) {
+ PhyPersonMandateContainer phyPersonMandateContainer = (PhyPersonMandateContainer) mandateContainer;
+ represented.setEIdentifier(getRepresentedStorkeIdentifier(mandateContainer));
+ represented.setGivenName(phyPersonMandateContainer.getPhyPersMandatorGivenName());
+ represented.setSurname(phyPersonMandateContainer.getPhyPersMandatorFamilyName());
+ represented.setDateOfBirth(phyPersonMandateContainer.getPhyPersMandatorBirthDate());
+ }
+
+ Logger.debug("Complex attribute extracted: " + sourceAttribute.getName());
+
+ return represented;
+ }
+
+
+ private MandateContentType getMandateContent(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException {
+ MandateContentType mandateContent = new MandateContentType();
+ try {
+ XMLGregorianCalendar validFrom = DatatypeFactory.newInstance().newXMLGregorianCalendar(mandateContainer.getMandateValidFrom());
+ XMLGregorianCalendar validTo = DatatypeFactory.newInstance().newXMLGregorianCalendar(mandateContainer.getMandateValidTo());
+ TimeRestrictionType timeRestriction = new TimeRestrictionType();
+ timeRestriction.setValidFrom(validFrom);
+ timeRestriction.setValidTo(validTo);
+ mandateContent.setTimeRestriction(timeRestriction);
+ } catch (DatatypeConfigurationException dte) {
+ Logger.error("Error converting date from mandate: " + mandateContainer.getMandateValidFrom() + ", " + mandateContainer.getMandateValidTo());
+ throw new MOAIDException("stork.20", new Object[]{});
+ }
+ mandateContent.setAQAA(this.QAALevel);
+ mandateContent.setOriginalMandate(originalContent);
+ mandateContent.setOriginalMandateType("application/xml");
+ TransactionLimitRestrictionType transactionLimit = new TransactionLimitRestrictionType();
+ mandateContent.setTransactionLimit(transactionLimit);
+ mandateContent.setIsJoint("");
+ mandateContent.setIsChained(false);
+ mandateContent.setTypeOfPower(mapPowersType(mandateContainer)); // TODO check
+ Logger.debug("Complex attribute extracted: " + sourceAttribute.getName());
+ return mandateContent;
+ }
+
+ public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) {
+ return true;
+ }
+
+ public String getDefaultActionName() {
+ return STORKProtocol.MANDATERETRIEVALREQUEST;
+ }
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java
new file mode 100644
index 000000000..c715b65eb
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.logging.Logger;
+import org.xml.sax.InputSource;
+
+import javax.xml.xpath.XPathExpressionException;
+import java.io.StringReader;
+
+/**
+ * Physical person representing physical person
+ * @author bsuzic
+ * Date: 4/30/14, Time: 11:29 AM
+ */
+public class PhyPersonMandateContainer extends MandateContainer {
+
+ private String phyPersMandatorIdentificationValue = null;
+ private String phyPersMandatorIdentificationType = null;
+ private String phyPersMandatorGivenName = null;
+ private String phyPersMandatorFamilyName = null;
+ private String phyPersMandatorBirthDate = null;
+
+ String localMethods[] = new String[]{"getPhyPersMandatorGivenName", "getPhyPersMandatorFamilyName", "getPhyPersMandatorBirthDate", "getPhyPersMandatorIdentificationValue",
+ "getPhyPersMandatorIdentificationType", "getMandateIssuePlace", "getMandateIssueDate", "getMandateIssueTime", "getSimpleMandateContent", "getMandateValidFrom",
+ "getMandateValidTo", "getPhysicalRepresentativeIdentificationValue", "getPhysicalRepresentativeIdentificationType", "getAnnotation",
+ "getPhysicalRepresentativeGivenName", "getPhysicalRepresentativeFamilyName", "getPhysicalRepresentativeBirthDate"
+ };
+
+
+ public PhyPersonMandateContainer(String mandate) throws XPathExpressionException, MOAIDException {
+ super(mandate);
+
+ setAnnotation(xPath.evaluate(S2Constants.MANDATE_ANNOTATION_QUERY, new InputSource(new StringReader(mandate))));
+ setPhyPersMandatorIdentificationType(xPath.evaluate(S2Constants.MANDATE_MANDATOR_PHYPERS_IDTYPE_QUERY, new InputSource(new StringReader(mandate))));
+ setPhyPersMandatorIdentificationValue(xPath.evaluate(S2Constants.MANDATE_MANDATOR_PHYPERS_IDVALUE_QUERY, new InputSource(new StringReader(mandate))));
+ setPhyPersMandatorGivenName(xPath.evaluate(S2Constants.MANDATE_MANDATOR_PHYPERS_GIVENNAME_QUERY, new InputSource(new StringReader(mandate))));
+ setPhyPersMandatorFamilyName(xPath.evaluate(S2Constants.MANDATE_MANDATOR_PHYPERS_FAMILYNAME_QUERY, new InputSource(new StringReader(mandate))));
+ setPhyPersMandatorBirthDate(xPath.evaluate(S2Constants.MANDATE_MANDATOR_PHYPERS_DATEOFBIRTH_QUERY, new InputSource(new StringReader(mandate))));
+ setMandateIssueDate(xPath.evaluate(S2Constants.MANDATE_ISSUEDDATE_QUERY, new InputSource(new StringReader(mandate))));
+ setMandateIssuePlace(xPath.evaluate(S2Constants.MANDATE_ISSUEDPLACE_QUERY, new InputSource(new StringReader(mandate))));
+ setMandateIssueTime(xPath.evaluate(S2Constants.MANDATE_ISSUEDTIME_QUERY, new InputSource(new StringReader(mandate))));
+ setMandateValidFrom(xPath.evaluate(S2Constants.MANDATE_SIMPLEMANDATECONTENT_VALIDFROM_QUERY, new InputSource(new StringReader(mandate))));
+ setMandateValidTo(xPath.evaluate(S2Constants.MANDATE_SIMPLEMANDATECONTENT_VALIDTO_QUERY, new InputSource(new StringReader(mandate))));
+ setPhysicalRepresentativeBirthDate(xPath.evaluate(S2Constants.MANDATE_REPRESENTATIVE_PHYPERS_DATEOFBIRTH_QUERY, new InputSource(new StringReader(mandate))));
+ setPhysicalRepresentativeFamilyName(xPath.evaluate(S2Constants.MANDATE_REPRESENTATIVE_PHYPERS_FAMILYNAME_QUERY, new InputSource(new StringReader(mandate))));
+ setPhysicalRepresentativeGivenName(xPath.evaluate(S2Constants.MANDATE_REPRESENTATIVE_PHYPERS_GIVENNAME_QUERY, new InputSource(new StringReader(mandate))));
+ setPhysicalRepresentativeIdentificationType(xPath.evaluate(S2Constants.MANDATE_REPRESENTATIVE_PHYPERS_IDTYPE_QUERY, new InputSource(new StringReader(mandate))));
+ setPhysicalRepresentativeIdentificationValue(xPath.evaluate(S2Constants.MANDATE_REPRESENTATIVE_PHYPERS_IDVALUE_QUERY, new InputSource(new StringReader(mandate))));
+ setSimpleMandateContent(xPath.evaluate(S2Constants.MANDATE_SIMPLEMANDATECONTENT_TXTDESC_QUERY, new InputSource(new StringReader(mandate))));
+
+ // check if all necessary fields are present
+ Logger.debug("Starting mandate structure validation");
+ try {
+ validateMandateStructure(localMethods); // TODO
+ } catch (Exception e) {
+ if (e instanceof MOAIDException) {
+ Logger.error("Could not validate mandate structure.");
+ throw new MOAIDException("stork.16", new Object[] {e.getMessage()}); // TODO
+ } else {
+ Logger.error("Error during mandate structure validation.");
+ throw new MOAIDException("stork.16", new Object[] {e.getMessage()}); // TODO
+ }
+
+ }
+ }
+
+
+
+ public String getPhyPersMandatorGivenName() {
+ return phyPersMandatorGivenName;
+ }
+
+ public void setPhyPersMandatorGivenName(String phyPersMandatorGivenName) {
+ this.phyPersMandatorGivenName = phyPersMandatorGivenName;
+ }
+
+ public String getPhyPersMandatorFamilyName() {
+ return phyPersMandatorFamilyName;
+ }
+
+ public void setPhyPersMandatorFamilyName(String phyPersMandatorFamilyName) {
+ this.phyPersMandatorFamilyName = phyPersMandatorFamilyName;
+ }
+
+ public String getPhyPersMandatorBirthDate() {
+ return phyPersMandatorBirthDate;
+ }
+
+ public void setPhyPersMandatorBirthDate(String phyPersMandatorBirthDate) {
+ // making it conform to STORK dateOfBirth specifications, removing dash
+ this.phyPersMandatorBirthDate = phyPersMandatorBirthDate.replaceAll("-","");
+ }
+
+ public String getPhyPersMandatorIdentificationValue() {
+ return phyPersMandatorIdentificationValue;
+ }
+
+ public void setPhyPersMandatorIdentificationValue(String phyPersMandatorIdentificationValue) {
+ this.phyPersMandatorIdentificationValue = phyPersMandatorIdentificationValue;
+ }
+
+ public String getPhyPersMandatorIdentificationType() {
+ return phyPersMandatorIdentificationType;
+ }
+
+ public void setPhyPersMandatorIdentificationType(String phyPersMandatorIdentificationType) {
+ this.phyPersMandatorIdentificationType = phyPersMandatorIdentificationType;
+ }
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/S2Constants.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/S2Constants.java
new file mode 100644
index 000000000..a560bdaff
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/S2Constants.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+/**
+ * @author bsuzic
+ * Date: 4/29/14, Time: 5:34 PM
+ */
+public interface S2Constants {
+ public static final String MANDATE_PREFIX = "mandate";
+ public static final String PERSONDATA_PREFIX = "persondata";
+ public static final String XMLDSIG_PREFIX = "xmldsig";
+
+ public static final String MANDATE_NS = "http://reference.e-government.gv.at/namespace/mandates/20040701#";
+ public static final String PERSONDATA_NS = "http://reference.e-government.gv.at/namespace/persondata/20020228#";
+ public static final String XMLDSIG_NS = "http://www.w3.org/2000/09/xmldsig#";
+
+ public static final String MANDATE_ANNOTATION_QUERY = "/mandate:Mandate/mandate:Annotation/text()";
+ public static final String MANDATE_REPRESENTATIVE_PHYPERS_IDVALUE_QUERY = "/mandate:Mandate/mandate:Representative/persondata:PhysicalPerson/persondata:Identification/persondata:Value/text()";
+ public static final String MANDATE_REPRESENTATIVE_PHYPERS_IDTYPE_QUERY = "/mandate:Mandate/mandate:Representative/persondata:PhysicalPerson/persondata:Identification/persondata:Type/text()";
+ public static final String MANDATE_REPRESENTATIVE_PHYPERS_GIVENNAME_QUERY = "/mandate:Mandate/mandate:Representative/persondata:PhysicalPerson/persondata:Name/persondata:GivenName/text()";
+ public static final String MANDATE_REPRESENTATIVE_PHYPERS_FAMILYNAME_QUERY = "/mandate:Mandate/mandate:Representative/persondata:PhysicalPerson/persondata:Name/persondata:FamilyName/text()";
+ public static final String MANDATE_REPRESENTATIVE_PHYPERS_DATEOFBIRTH_QUERY = "/mandate:Mandate/mandate:Representative/persondata:PhysicalPerson/persondata:DateOfBirth/text()";
+ public static final String MANDATE_MANDATOR_CORPBODY_IDVALUE_QUERY = "/mandate:Mandate/mandate:Mandator/persondata:CorporateBody/persondata:Identification/persondata:Value/text()";
+ public static final String MANDATE_MANDATOR_CORPBODY_IDTYPE_QUERY = "/mandate:Mandate/mandate:Mandator/persondata:CorporateBody/persondata:Identification/persondata:Type/text()";
+ public static final String MANDATE_MANDATOR_CORPBODY_FULLNAME_QUERY = "/mandate:Mandate/mandate:Mandator/persondata:CorporateBody/persondata:FullName/text()";
+ public static final String MANDATE_ISSUEDPLACE_QUERY = "/mandate:Mandate/mandate:Issued/mandate:Place/text()";
+ public static final String MANDATE_ISSUEDDATE_QUERY = "/mandate:Mandate/mandate:Issued/mandate:Date/text()";
+ public static final String MANDATE_ISSUEDTIME_QUERY = "/mandate:Mandate/mandate:Issued/mandate:Time/text()";
+ public static final String MANDATE_SIMPLEMANDATECONTENT_TXTDESC_QUERY = "/mandate:Mandate/mandate:SimpleMandateContent/mandate:TextualDescription/text()";
+ public static final String MANDATE_SIMPLEMANDATECONTENT_VALIDFROM_QUERY = "/mandate:Mandate/mandate:SimpleMandateContent/mandate:TimeConstraint/mandate:ValidFrom/text()";
+ public static final String MANDATE_SIMPLEMANDATECONTENT_VALIDTO_QUERY = "/mandate:Mandate/mandate:SimpleMandateContent/mandate:TimeConstraint/mandate:ValidTo/text()";
+
+ public static final String MANDATE_MANDATOR_PHYPERS_IDVALUE_QUERY = "/mandate:Mandate/mandate:Mandator/persondata:PhysicalPerson/persondata:Identification/persondata:Value/text()";
+ public static final String MANDATE_MANDATOR_PHYPERS_IDTYPE_QUERY = "/mandate:Mandate/mandate:Mandator/persondata:PhysicalPerson/persondata:Identification/persondata:Type/text()";
+ public static final String MANDATE_MANDATOR_PHYPERS_GIVENNAME_QUERY = "/mandate:Mandate/mandate:Mandator/persondata:PhysicalPerson/persondata:Name/persondata:GivenName/text()";
+ public static final String MANDATE_MANDATOR_PHYPERS_FAMILYNAME_QUERY = "/mandate:Mandate/mandate:Mandator/persondata:PhysicalPerson/persondata:Name/persondata:FamilyName/text()";
+ public static final String MANDATE_MANDATOR_PHYPERS_DATEOFBIRTH_QUERY = "/mandate:Mandate/mandate:Mandator/persondata:PhysicalPerson/persondata:DateOfBirth/text()";
+
+ public static final String IDENTIFICATION_TYPE_COMPANY = "urn:publicid:gv.at:baseid+XFN";
+ public static final String IDENTIFICATION_TYPE_ASSOCIATION = "urn:publicid:gv.at:baseid+XZVR";
+ public static final String IDENTIFICATION_TYPE_OTHERS = "urn:publicid:gv.at:baseid+XERSB";
+
+
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java
new file mode 100644
index 000000000..123d32af4
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java
@@ -0,0 +1,49 @@
+/*
+ * 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.protocols.stork2;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author tlenz
+ *
+ */
+public class STORKPVPUtilits {
+
+ public static final List<String> attributesRequirePVPAuthentication =
+ Arrays.asList("ECApplicationRole", "MSOrganization");
+
+
+
+ public static boolean performAuthenticationOnNationalIDP(MOASTORKRequest moastorkRequest) {
+ for (String el : attributesRequirePVPAuthentication) {
+ if (moastorkRequest.getPersonalAttributeList().containsKey(el)) {
+ return true;
+
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKProtocol.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKProtocol.java
new file mode 100644
index 000000000..071b5ae8a
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKProtocol.java
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.moduls.IAction;
+import at.gv.egovernment.moa.id.moduls.IModulInfo;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import eu.stork.peps.auth.commons.*;
+import eu.stork.peps.auth.engine.STORKSAMLEngine;
+import eu.stork.peps.exceptions.STORKSAMLEngineException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+
+/**
+ * Stork 2 Protocol Support
+ *
+ * @author bsuzic
+ */
+public class STORKProtocol extends MOAIDAuthConstants implements IModulInfo {
+
+ public static final String NAME = STORKProtocol.class.getName();
+ public static final String PATH = "id_stork2";
+
+ public static final String AUTHENTICATIONREQUEST = "AuthenticationRequest";
+ public static final String ATTRIBUTE_COLLECTOR = "AttributeCollector";
+ public static final String MANDATERETRIEVALREQUEST = "MandateRetrievalRequest";
+ public static final String CONSENT_EVALUATOR = "ConsentEvaluator";
+
+ private static HashMap<String, IAction> actions = new HashMap<String, IAction>();
+
+ static {
+ actions.put(AUTHENTICATIONREQUEST, new AuthenticationRequest());
+ actions.put(ATTRIBUTE_COLLECTOR, new AttributeCollector());
+ actions.put(CONSENT_EVALUATOR, new ConsentEvaluator());
+ actions.put(MANDATERETRIEVALREQUEST, new MandateRetrievalRequest());
+ }
+
+ public String getName() {
+ return NAME;
+ }
+
+ public String getPath() {
+ return PATH;
+ }
+
+ public IAction getAction(String action) {
+ return actions.get(action);
+ }
+
+ public STORKProtocol() {
+ super();
+ }
+
+ /*
+ First request step - send it to BKU selection for user authentication. After the user credentials
+ and other info are obtained, in the second step the request will be processed and the user redirected
+ */
+ public IRequest preProcess(HttpServletRequest request, HttpServletResponse response, String action,
+ String sessionId, String transactionId) throws MOAIDException {
+ Logger.info("Starting preprocessing for Stork2 protocol");
+ Logger.debug("Request method: " + request.getMethod());
+ Logger.debug("Request content length: " + request.getContentLength());
+ Logger.debug("Initiating action: " + action);
+
+ MOASTORKRequest STORK2Request = new MOASTORKRequest();
+ MOASTORKResponse STORK2Response = new MOASTORKResponse();
+
+
+ if (AttributeCollector.class.getSimpleName().equals(action) || ConsentEvaluator.class.getSimpleName().equals(action))
+ return STORK2Request;
+
+
+ if (request.getParameter("SAMLResponse") != null) { // TODO check attribute collector
+ //extract STORK Response from HTTP Request
+ byte[] decSamlToken;
+ try {
+ decSamlToken = PEPSUtil.decodeSAMLToken(request.getParameter("SAMLResponse"));
+ } catch (NullPointerException e) {
+ if (request.getRemoteHost().contains("129.27.142")) {
+ Logger.warn("Availability check by " + request.getRemoteHost() + " on URI: " + request.getRequestURI());
+ } else {
+ Logger.error("Unable to retrieve STORK Request for host: " + request.getRemoteHost() + " and URI: " + request.getRequestURI(), e);
+ }
+ throw new MOAIDException("stork.04", null);
+ }
+
+ //Get SAMLEngine instance
+ STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
+
+ STORKAuthnResponse authnResponse = null;
+
+
+ // check if valid authn request is contained
+ try {
+ authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, request.getRemoteAddr());
+ } catch (STORKSAMLEngineException ex) {
+ Logger.error("Unable to validate Stork AuthenticationResponse: " + ex.getMessage());
+ }
+
+ STORK2Response.setSTORKAuthnResponseToken(decSamlToken);
+
+ return STORK2Response;
+
+ } else if (request.getParameter("SAMLRequest") != null) {
+
+ //extract STORK Response from HTTP Request
+ byte[] decSamlToken;
+ try {
+ decSamlToken = PEPSUtil.decodeSAMLToken(request.getParameter("SAMLRequest"));
+ } catch (NullPointerException e) {
+ if (request.getRemoteHost().contains("129.27.142")) {
+ Logger.warn("Availability check by " + request.getRemoteHost() + " on URI: " + request.getRequestURI());
+ } else {
+ Logger.error("Unable to retrieve STORK Request for host: " + request.getRemoteHost() + " and URI: " + request.getRequestURI(), e);
+ }
+ throw new MOAIDException("stork.04", null);
+ }
+
+ //Get SAMLEngine instance
+ STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
+
+ STORKAuthnRequest authnRequest = null;
+ STORKAttrQueryRequest attrRequest = null;
+
+ // check if valid authn request is contained
+ try {
+ authnRequest = engine.validateSTORKAuthnRequest(decSamlToken);
+
+ } catch (STORKSAMLEngineException ex) {
+ Logger.error("Unable to validate Stork AuthenticationRequest: " + ex.getMessage());
+
+ } catch (ClassCastException e) {
+ // we do not have a authnRequest
+ // check if a valid attr request is container
+ try {
+ attrRequest = engine.validateSTORKAttrQueryRequest(decSamlToken);
+
+ } catch (STORKSAMLEngineException ex) {
+ Logger.error("Unable to validate Stork AuthenticationRequest: " + ex.getMessage());
+
+ }
+ }
+
+ // if there is no authn or attr request, raise error
+ if ((authnRequest == null) && (attrRequest == null)) {
+ Logger.error("There is no authentication or attribute request contained.");
+ throw new MOAIDException("stork.14", null);
+ }
+ // list attributes in the request
+ try {
+ for (PersonalAttribute personalAttribute : authnRequest.getPersonalAttributeList()) {
+ Logger.debug("Personal attribute found in request: " + personalAttribute.getName() + " isRequired: " + personalAttribute.isRequired());
+ }
+ } catch (Exception e) {
+ Logger.error("Exception, attributes: " + e.getMessage());
+ }
+
+ STORK2Request.setSTORKAuthnRequest(authnRequest);
+ STORK2Request.setSTORKAttrRequest(attrRequest);
+
+ //check if OA is instance of VIDP or STORKPVPGateway
+ OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(STORK2Request.getOAURL());
+ if (oaParam == null)
+ throw new AuthenticationException("stork.12", new Object[]{STORK2Request.getOAURL()});
+
+ else {
+ STORK2Request.setOnlineApplicationConfiguration(oaParam);
+ if (oaParam.isSTORKPVPGateway()) {
+ if (MiscUtil.isNotEmpty(oaParam.getSTORKPVPForwardEntity())) {
+ Logger.info("Received request for STORK->PVP gateway. " +
+ "Forward to PVP portal with entiyID " + oaParam.getSTORKPVPForwardEntity() +
+ " ..." );
+ STORK2Request.setRequestedIDP(oaParam.getSTORKPVPForwardEntity());
+
+ } else {
+ Logger.error("InterfederatedGateway configuration with ID " + STORK2Request.getOAURL() +
+ " not configure a forward entityID.");
+ throw new MOAIDException("", null);
+
+ }
+ }
+
+ }
+
+ return STORK2Request;
+ } else {
+ throw new MOAIDException("stork.14", null); // TODO Specify message
+ }
+ }
+
+ public IAction canHandleRequest(HttpServletRequest request, HttpServletResponse response) {
+ return null;
+ }
+
+ public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, IRequest protocolRequest) throws Throwable {
+ return false;
+ }
+
+ public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) {
+ return false;
+ }
+}
+
+
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/SimpleNamespaceContext.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/SimpleNamespaceContext.java
new file mode 100644
index 000000000..2c2df3e54
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/SimpleNamespaceContext.java
@@ -0,0 +1,83 @@
+/*
+ * 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.protocols.stork2;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.xml.namespace.NamespaceContext;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SimpleNamespaceContext implements NamespaceContext {
+
+ HashMap<String, String> prefMap = null;
+ /**
+ * @param prefMap
+ */
+ SimpleNamespaceContext(HashMap<String, String> prefMap) {
+ this.prefMap = prefMap;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.xml.namespace.NamespaceContext#getNamespaceURI(java.lang.String)
+ */
+ @Override
+ public String getNamespaceURI(String prefix) {
+ if (prefMap.containsKey(prefix))
+ return prefMap.get(prefix);
+ else
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.xml.namespace.NamespaceContext#getPrefix(java.lang.String)
+ */
+ @Override
+ public String getPrefix(String namespaceURI) {
+ if (prefMap.containsValue(namespaceURI)) {
+ Set<Entry<String, String>> set = prefMap.entrySet();
+ for (Entry<String, String> el : set) {
+ if (el.getValue().equals(namespaceURI))
+ return el.getKey();
+
+ }
+ }
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.xml.namespace.NamespaceContext#getPrefixes(java.lang.String)
+ */
+ @Override
+ public Iterator getPrefixes(String namespaceURI) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/UnsupportedAttributeException.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/UnsupportedAttributeException.java
new file mode 100644
index 000000000..31b9c9c0a
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/UnsupportedAttributeException.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.protocols.stork2;
+
+public class UnsupportedAttributeException extends Exception {
+
+ private static final long serialVersionUID = -7720066381435378111L;
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/AttributeProvider.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/AttributeProvider.java
new file mode 100644
index 000000000..aaf13a779
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/AttributeProvider.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * 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.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.MOASTORKRequest;
+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 implements Comparable<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 currentProviderConfiguredAttributes the list of attributes to be acquired
+ * @param moastorkRequest 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 currentProviderConfiguredAttributes, MOASTORKRequest moastorkRequest, IAuthData authData) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException, MOAIDException;
+
+ public IPersonalAttributeList acquire(List<PersonalAttribute> attributes, MOASTORKRequest moastorkRequest, IAuthData authData) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException, MOAIDException {
+ if (attributes.size() == 1) {
+ return acquire(attributes.get(0), moastorkRequest, 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;
+ }
+
+
+ /**
+ * Returns the sequence priority of this attribute provider.
+ * Providers with small numbers are requested first.
+ *
+ * @return a sequence priority of this provider
+ */
+ public abstract int getPriority();
+
+ /**
+ * Compare the sequence priority of two attribute providers
+ * @param o attribute provider
+ * @return 0 if priority is equal
+ * @return -1 if priority if this is higher then from o
+ * @return +1 if priority if o is higher then from this
+ */
+ @Override
+ public int compareTo(AttributeProvider o) {
+ if (this.getPriority() == o.getPriority())
+ return 0;
+
+ if (this.getPriority() < o.getPriority())
+ return -1;
+
+ else
+ return +1;
+ }
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/EHvdAttributeProviderPlugin.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/EHvdAttributeProviderPlugin.java
new file mode 100644
index 000000000..bd1576020
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/EHvdAttributeProviderPlugin.java
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * 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.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.MOASTORKRequest;
+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.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType;
+import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.IsHealthCareProfessionalType;
+import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.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 supportedAttributes
+ */
+ 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, MOASTORKRequest moastorkRequest, 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") || !collection.get("Type").equals("Medical doctor")) {
+ // the citizen is no HCP
+ acquiredAttribute = new PersonalAttribute("isHealthCareProfessional", false, new ArrayList<String>(), AttributeStatusType.NOT_AVAILABLE.value());
+ } else {
+ // go on and parse the data
+ IsHealthCareProfessionalType result = new IsHealthCareProfessionalType();
+
+ // TODO: we do not have any list of possible values yet. Fix as soon as we get some.
+// if (collection.get("Type").equals("Medical doctor"))
+ result.setTypeOfHCP("physician");
+
+ result.setNameOfOrganisation(collection.get("NameOfOrganisation"));
+ //result.setTypeOfOrganisation("Unknown"); // TODO used in previous version, check what to do with this
+
+ 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, AttributeStatusType.AVAILABLE.value());
+ }
+
+ // 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(), moastorkRequest.getSpCountry()));
+ result.add(new PersonalAttribute("eIdentifier", false, value, AttributeStatusType.AVAILABLE.value()));
+
+ 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();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider#getPriority()
+ */
+ @Override
+ public int getPriority() {
+ return 99;
+ }
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java
new file mode 100644
index 000000000..f671f0807
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * 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.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.MOASTORKRequest;
+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";
+ }
+
+ // TODO check if used
+ @Override
+ protected IPersonalAttributeList acquire(PersonalAttribute attribute, MOASTORKRequest moastorkRequest, IAuthData authData) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException, MOAIDException {
+ Logger.info("Acquiring attribute: " + attribute.getName() + ", by: " + getAttrProviderName());
+ this.spCountryCode = moastorkRequest.getSpCountry();
+ 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();
+ }
+
+ // check if there is eIdentifier included and add if necessary
+// if (!requestedAttributes.containsKey("eIdentifier")) {
+// PersonalAttribute eIdentifier = new PersonalAttribute();
+ // eIdentifier.setName("eIdentifier");
+// eIdentifier.setIsRequired(true);
+// requestedAttributes.add(eIdentifier);
+// }
+
+ Logger.info("Thrown external request by: " + getAttrProviderName());
+ throw new ExternalAttributeRequestRequiredException(this);
+ }
+
+ @Override
+ public IPersonalAttributeList acquire(List<PersonalAttribute> attributes, MOASTORKRequest moastorkRequest, IAuthData moasession) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException, MOAIDException {
+ Logger.info("Acquiring " + attributes.size() + " attributes, by: " + getAttrProviderName());
+ this.spCountryCode = moastorkRequest.getSpCountry();
+ 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);
+ }
+
+ // continue with other attribute providers if there are no attributes current provider is able to handle
+ if (requestedAttributes.size() == 0) {
+ Logger.info("Attribute(s) " + attributes.toString() + " not supported by the provider: " + getAttrProviderName());
+ throw new UnsupportedAttributeException();
+ }
+
+
+
+ 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;
+
+ if ((spCountryCode == null) || (spCountryCode.length()<2)) {
+ spCountryCode = oaParam.getTarget();
+ Logger.info("Setting spcountry target: " + oaParam.getTarget());
+ Logger.info("idlink ident " + oaParam.getIdentityLinkDomainIdentifier());
+ Logger.info("idlink type " + oaParam.getIdentityLinkDomainIdentifierType());
+ Logger.info("Setting spcountry target friendly : " + oaParam.getTargetFriendlyName());
+ Logger.info("Oatype : " + oaParam.getOaType());
+ Logger.info("puburl : " + oaParam.getPublicURLPrefix());
+ if ("STORK".equals(oaParam.getIdentityLinkDomainIdentifierType())) {
+
+ spCountryCode = oaParam.getIdentityLinkDomainIdentifier().substring(oaParam.getIdentityLinkDomainIdentifier().length()-2);
+ Logger.info("Set to " +spCountryCode);
+ }
+
+ }
+
+ // TODO ensure that other providers request eidentifier
+ // check if there is eIdentifier included and add if necessary
+ if (!requestedAttributes.containsKey("eIdentifier")) {
+ PersonalAttribute eIdentifier = new PersonalAttribute();
+ eIdentifier.setName("eIdentifier");
+ eIdentifier.setIsRequired(true);
+ requestedAttributes.add(eIdentifier);
+ }
+
+ //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");
+ attributeRequest.setQaa(oaParam.getQaaLevel());
+
+ if (attributeRequest.getQaa() == 0 ) {
+ attributeRequest.setQaa(4); // workaround
+ }
+
+
+
+ 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("UTF-8"));
+ } 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; //
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider#getPriority()
+ */
+ @Override
+ public int getPriority() {
+ return 99;
+ }
+}
+
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java
new file mode 100644
index 000000000..7f06c604b
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java
@@ -0,0 +1,238 @@
+/*
+ * 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.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.MOASTORKRequest;
+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.STORKAttrQueryRequest;
+import eu.stork.peps.auth.commons.STORKAttrQueryResponse;
+import eu.stork.peps.auth.commons.STORKAuthnRequest;
+import eu.stork.peps.auth.commons.STORKAuthnResponse;
+import eu.stork.peps.auth.engine.STORKSAMLEngine;
+import eu.stork.peps.exceptions.STORKSAMLEngineException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class PVPAuthenticationProvider extends AttributeProvider {
+
+ private String destination = null;
+ private MOASTORKRequest moastorkRequest = null;
+
+ /**
+ * @param attributes
+ * @param attributes2
+ */
+ public PVPAuthenticationProvider(String url, String attributes) {
+ super(attributes);
+ this.destination = url;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider#acquire(eu.stork.peps.auth.commons.PersonalAttribute, java.lang.String, at.gv.egovernment.moa.id.data.IAuthData)
+ */
+ @Override
+ protected IPersonalAttributeList acquire(PersonalAttribute attribute,
+ MOASTORKRequest moastorkRequest, IAuthData authData)
+ throws UnsupportedAttributeException,
+ ExternalAttributeRequestRequiredException, MOAIDException {
+
+ this.moastorkRequest = moastorkRequest;
+ // break if we cannot handle the requested attribute
+ if (!getSupportedAttributeNames().contains(attribute.getName())) {
+ Logger.info("Attribute " + attribute.getName() + " not supported by the provider: " + getAttrProviderName());
+ throw new UnsupportedAttributeException();
+
+ }
+
+ Logger.info("Thrown external request by: " + getAttrProviderName());
+ throw new ExternalAttributeRequestRequiredException(this);
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider#performRedirect(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.config.auth.OAAuthParameter)
+ */
+ @Override
+ 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;
+ String spCountryCode = moastorkRequest.getSpCountry();
+
+ if ((spCountryCode == null) || (spCountryCode.length()<2)) {
+ spCountryCode = oaParam.getTarget();
+ Logger.info("Setting spcountry target: " + oaParam.getTarget());
+ Logger.info("idlink ident " + oaParam.getIdentityLinkDomainIdentifier());
+ Logger.info("idlink type " + oaParam.getIdentityLinkDomainIdentifierType());
+ Logger.info("Setting spcountry target friendly : " + oaParam.getTargetFriendlyName());
+ Logger.info("Oatype : " + oaParam.getOaType());
+ Logger.info("puburl : " + oaParam.getPublicURLPrefix());
+ if ("STORK".equals(oaParam.getIdentityLinkDomainIdentifierType())) {
+
+ spCountryCode = oaParam.getIdentityLinkDomainIdentifier().substring(oaParam.getIdentityLinkDomainIdentifier().length()-2);
+ Logger.info("Set to " +spCountryCode);
+ }
+
+ }
+
+ //generate AttrQueryRequest
+ STORKAuthnRequest authRequest = new STORKAuthnRequest();
+ authRequest.setDestination(destination);
+ authRequest.setAssertionConsumerServiceURL(url);
+ authRequest.setIssuer(HTTPUtils.getBaseURL(req));
+ authRequest.setQaa(oaParam.getQaaLevel());
+ authRequest.setSpInstitution(spInstitution);
+ authRequest.setCountry(spCountryCode);
+ authRequest.setSpCountry(spCountryCode);
+ authRequest.setSpApplication(spApplication);
+ authRequest.setProviderName(spApplication);
+ authRequest.setSpSector(spSector);
+ authRequest.setPersonalAttributeList(moastorkRequest.getPersonalAttributeList());
+
+ authRequest.setCitizenCountryCode("AT");
+ //authRequest.setQaa(oaParam.getQaaLevel());
+ authRequest.setQaa(moastorkRequest.getStorkAuthnRequest().getQaa());
+
+
+
+
+ Logger.info("STORK AttrRequest successfully assembled.");
+
+ STORKSAMLEngine samlEngine = STORKSAMLEngine.getInstance("VIDP");
+ try {
+
+ authRequest = samlEngine.generateSTORKAuthnRequest(authRequest);
+ } catch (STORKSAMLEngineException e) {
+ Logger.error("Could not sign STORK SAML AttrRequest.", e);
+ throw new MOAIDException("stork.00", null);
+ }
+
+ Logger.info("STORK AttrRequest successfully signed!");
+
+ //validate AuthnRequest
+ try {
+ samlEngine.validateSTORKAuthnRequest(authRequest.getTokenSaml());
+ } catch (STORKSAMLEngineException e) {
+ Logger.error("STORK SAML AuthnRequest not valid.", e);
+ throw new MOAIDException("stork.01", null);
+ }
+
+ Logger.debug("STORK AuthnRequest successfully internally validated.");
+
+ 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(authRequest.getTokenSaml()));
+ context.put("action", destination);
+
+ StringWriter writer = new StringWriter();
+ template.merge(context, writer);
+
+ resp.getOutputStream().write(writer.toString().getBytes("UTF-8"));
+
+ } catch (Exception e) {
+ Logger.error("Error sending STORK SAML AttrRequest.", e);
+ throw new MOAIDException("stork.11", null);
+
+ }
+ Logger.info("STORK AttrRequest successfully rendered!");
+
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider#parse(javax.servlet.http.HttpServletRequest)
+ */
+ @Override
+ public IPersonalAttributeList parse(HttpServletRequest httpReq)
+ throws UnsupportedAttributeException, MOAIDException {
+
+ throw new 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");
+//
+// STORKAuthnResponse authnResponse = null;
+// try {
+// //validate SAML Token
+// Logger.debug("Starting validation of SAML response");
+// authnResponse = engine.validateSTORKAuthnResponse(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 authnResponse.getPersonalAttributeList();
+
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider#getPriority()
+ */
+ @Override
+ public int getPriority() {
+ return 1;
+ }
+
+ public String getAttrProviderName() {
+ return this.getClass().getName();
+ }
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java
new file mode 100644
index 000000000..def89d0d9
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java
@@ -0,0 +1,688 @@
+/*******************************************************************************
+ * 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.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.stream.StreamSource;
+import javax.xml.ws.Service;
+import javax.xml.ws.soap.SOAPBinding;
+import javax.xml.ws.BindingProvider;
+
+import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType;
+
+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.AuthConfiguration;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+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.MOASTORKRequest;
+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 at.gv.egovernment.moa.util.Base64Utils;
+import eu.stork.oasisdss.api.ApiUtils;
+import eu.stork.oasisdss.api.LightweightSourceResolver;
+import eu.stork.oasisdss.api.ResultMajor;
+import eu.stork.oasisdss.api.exceptions.ApiUtilsException;
+import eu.stork.oasisdss.profile.AnyType;
+import eu.stork.oasisdss.profile.Base64Data;
+import eu.stork.oasisdss.profile.DocumentType;
+import eu.stork.oasisdss.profile.DocumentWithSignature;
+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;
+
+ try {
+ AuthConfiguration authConfigurationProvider = AuthConfigurationProviderFactory.getInstance();
+ dtlUrl = authConfigurationProvider.getDocumentServiceUrl();
+ Logger.info ("SignedDocAttributeRequestProvider, using dtlUrl:"+dtlUrl);
+ } catch (Exception e) {
+ dtlUrl = "http://testvidp.buergerkarte.at/DocumentService/DocumentService";
+ e.printStackTrace();
+ Logger.error("Loading documentservice url failed, using default value:"+dtlUrl);
+ }
+
+// Properties props = new Properties();
+// try {
+// props.load(DatabaseConnectorMySQLImpl.class.getResourceAsStream("docservice.properties"));
+// dtlUrl = props.getProperty("docservice.url");
+// } catch (IOException e) {
+// dtlUrl = "http://testvidp.buergerkarte.at/DocumentService/DocumentService";
+// Logger.error("Loading DTL config failed, using default value:"+dtlUrl);
+// e.printStackTrace();
+// }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#acquire(java
+ * .lang.String)
+ */
+ @Override
+ protected IPersonalAttributeList acquire(PersonalAttribute attribute, MOASTORKRequest moastorkRequest, IAuthData authData) throws UnsupportedAttributeException,
+ ExternalAttributeRequestRequiredException {
+ if(!attributes.contains(attribute.getName())) {
+ throw new UnsupportedAttributeException();
+ }
+
+ requestedAttribute = attribute;
+ try
+ {
+ String tmp = requestedAttribute.getValue().get(0);
+ }catch(Exception e)
+ {
+ Logger.info("SignedDocAttributeProvide failed:"+e.toString());
+ throw new UnsupportedAttributeException();
+ }
+
+ 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 base64 = httpReq.getParameter("signresponse");
+ Logger.debug("signresponse url: " + httpReq.getRequestURI().toString());
+ Logger.debug("signresponse querystring: " + httpReq.getQueryString());
+ Logger.debug("signresponse method: " + httpReq.getMethod());
+ Logger.debug("signresponse content type: " + httpReq.getContentType());
+ Logger.debug("signresponse parameter:"+base64);
+ String signResponseString = new String(Base64Utils.decode(base64, false), "UTF8");
+ Logger.debug("RECEIVED signresponse:"+signResponseString);
+ //create SignResponse object
+ Source response = new StreamSource(new java.io.StringReader(signResponseString));
+ SignResponse signResponse = ApiUtils.unmarshal(response, SignResponse.class);
+ //Check if Signing was successfully or not
+
+ if(!signResponse.getResult().getResultMajor().equals(ResultMajor.RESULT_MAJOR_SUCCESS))
+ {
+ //Pass unmodifed or unmarshal & marshal??
+ InputStream istr = ApiUtils.marshalToInputStream(signResponse);
+ StringWriter writer = new StringWriter();
+ IOUtils.copy(istr, writer, "UTF-8");
+ signResponseString = writer.toString();
+ Logger.info("SignResponse with error (unmodified):"+signResponseString);
+ istr.close();
+ }
+ else
+ {
+ //extract doc from signresponse
+ DataSource dataSource = LightweightSourceResolver.getDataSource(signResponse);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ IOUtils.copy(dataSource.getInputStream(), baos);
+ byte[] data = baos.toByteArray();
+ baos.close();
+
+ //update doc in DTL
+ String docId, dssId = "";
+ docId = signResponse.getDocUI();
+ //For reference dssId equals docId
+ dssId = docId;
+ if (dssId != null && data!=null)
+ {
+ boolean success = false;
+ try{
+ success = updateDocumentInDtl(data, docId, signResponseString);
+ }catch(Exception e){//No document service used?
+ Logger.info("No document service used?");
+ e.printStackTrace();
+ success = false;
+ }
+ if(success)
+ {
+ // set the url in the SignResponse
+ DocumentWithSignature documentWithSignature = new DocumentWithSignature();
+ DocumentType value = new DocumentType();
+ if(dtlUrl.endsWith("?wsdl"))
+ {
+ String tmp = dtlUrl.replace("?wsdl", "");
+ Logger.debug("DocumentUrl ends with ? wsdl, using "+tmp+" instead.");
+ value.setDocumentURL(tmp);
+ }
+ else
+ {
+ value.setDocumentURL(dtlUrl);
+ }
+ documentWithSignature.setDocument(value);
+ if(signResponse.getOptionalOutputs()!=null)
+ {
+ //signResponse.getOptionalOutputs().getAny().add(documentWithSignature);
+ for(Object o :signResponse.getOptionalOutputs().getAny())
+ {
+ if(o instanceof DocumentWithSignature)
+ {
+ signResponse.getOptionalOutputs().getAny().remove(o);
+ signResponse.getOptionalOutputs().getAny().add(documentWithSignature);
+ break;
+ }
+ }
+ }
+ else
+ {
+ AnyType anytype = new AnyType();
+ anytype.getAny().add(documentWithSignature);
+ signResponse.setOptionalOutputs(anytype );
+ }
+
+ // 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();
+ Logger.info("SignResponse overwritten:"+signResponseString);
+ istr.close();
+ }
+ else
+ {
+ //No document service used?
+ // do nothing....
+ //TODO temporary fix because document is deleted after fetching => SP can't download Doc
+ //Add doc to Signresponse
+
+ DocumentWithSignature documentWithSignature = new DocumentWithSignature();
+ DocumentType value = new DocumentType();
+ if(signResponse.getProfile().toLowerCase().contains("xades"))
+ {
+ value.setBase64XML(data);
+ }
+ else
+ {
+ Base64Data base64data = new Base64Data();
+ base64data.setValue(data);
+ base64data.setMimeType(dataSource.getContentType());
+ value.setBase64Data(base64data);
+ }
+ documentWithSignature.setDocument(value);
+ if(signResponse.getOptionalOutputs()!=null)
+ {
+ //signResponse.getOptionalOutputs().getAny().add(documentWithSignature);
+ for(Object o :signResponse.getOptionalOutputs().getAny())
+ {
+ if(o instanceof DocumentWithSignature)
+ {
+ signResponse.getOptionalOutputs().getAny().remove(o);
+ signResponse.getOptionalOutputs().getAny().add(documentWithSignature);
+ break;
+ }
+ }
+ }
+ else
+ {
+ AnyType anytype = new AnyType();
+ anytype.getAny().add(documentWithSignature);
+ signResponse.setOptionalOutputs(anytype );
+ }
+
+ // 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();
+ Logger.info("SignResponse overwritten:"+signResponseString);
+ istr.close();
+ }
+ }
+ 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,
+ AttributeStatusType.AVAILABLE.value());
+
+ // 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);
+ throw new UnsupportedAttributeException();
+ }
+ }
+
+ /*
+ * (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...");
+ Logger.info("performRedirect url:"+url);
+ 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);
+ Logger.debug("performRedirect, signrequest:"+signRequestString);
+ Source signDoc = new StreamSource(new java.io.StringReader(signRequestString));
+ SignRequest signRequest = ApiUtils.unmarshal(signDoc, SignRequest.class);
+ try{
+ //search for DTL link
+ String dtlURL = getDtlUrlFromRequest(signRequest);
+ String docId = signRequest.getDocUI();
+
+ if(dtlURL!=null)
+ {
+ String docRequest = getDocTransferRequest(docId, dtlURL);//dtlUrl
+
+ byte[] data = getDocumentFromDtl(docRequest, dtlURL);//dtlUrl
+
+ //load doc from DTL
+ Logger.debug("data:"+data+" "+data.length);
+ try{
+ Logger.trace("data:"+new String(data,"UTF-8"));
+ }catch(Exception e)
+ {
+ Logger.trace("data: creating String failed:"+e);
+ }
+ String mime = getDocumentMimeFromDtl(docId, dtlURL);//dtlUrl
+ Logger.debug("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);
+
+ String documentId = null;
+ Object objDoc = signRequest.getInputDocuments().getDocumentOrTransformedDataOrDocumentHash().get(0);
+ if (objDoc != null && objDoc instanceof DocumentType)
+ {
+ DocumentType document = (DocumentType)objDoc;
+ documentId = document.getID();
+ }
+ DocumentType document = new DocumentType();
+ if(documentId != null)
+ document.setID(documentId);
+ if(signRequest.getProfile().toLowerCase().contains("xades"))
+ {
+ document.setBase64XML(data);
+ }
+ else
+ {
+ 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();
+ Logger.info("Signrequest overwritten");
+ Logger.debug("Signrequest overwritten:"+signRequestString);
+ istr.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Exception("Could not marshall sign request", e);
+ }
+ }
+ else//Do not modify signRequest, document is already included
+ {
+
+ }
+ }catch(Exception e)
+ {
+ Logger.info("No documentservice used?");
+ e.printStackTrace();
+ }
+
+ context.put("signrequest", Base64Utils.encode(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("UTF-8"));
+ } 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
+ return null;//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
+ {
+ Logger.debug("getDocumentFromDtl:"+dtlUrl);
+ 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
+ {
+ String spCountry = docId.substring(0, docId.indexOf("/"));
+ final STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
+ STORKAttrQueryRequest req = new STORKAttrQueryRequest();
+ req.setAssertionConsumerServiceURL(dtlUrl);
+ req.setDestination(destinationUrl);
+ req.setSpCountry(spCountry);
+ 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 updateDocumentInDtl", e);
+ }
+
+ return success;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider#getPriority()
+ */
+ @Override
+ public int getPriority() {
+ return 99;
+ }
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/StorkAttributeRequestProvider.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/StorkAttributeRequestProvider.java
new file mode 100644
index 000000000..5ee0e380e
--- /dev/null
+++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/StorkAttributeRequestProvider.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * 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.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.MOASTORKRequest;
+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, MOASTORKRequest moastorkRequest, IAuthData authData)
+ throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException {
+
+ if (!attributes.contains(attribute.getName()))
+ throw new UnsupportedAttributeException();
+
+ this.spCountryCode = moastorkRequest.getSpCountry();
+
+ 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("Using citizen country code: " + attributeRequest.getCitizenCountryCode());
+ 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("UTF-8"));
+ } catch (Exception e) {
+ Logger.error("Error sending STORK SAML AttrRequest.", e);
+ throw new MOAIDException("stork.11", null);
+ }
+ Logger.info("STORK AttrRequest successfully rendered!");
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider#getPriority()
+ */
+ @Override
+ public int getPriority() {
+ return 99;
+ }
+
+}
+