diff options
Diffstat (limited to 'id/server')
16 files changed, 721 insertions, 14 deletions
diff --git a/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml b/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml index b63d413d0..59d6d6cce 100644 --- a/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml +++ b/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml @@ -57,6 +57,10 @@ <to type="forward">/dispatcher?mod=id_stork2&action=AuthenticationRequest&%{query-string}</to> </rule> <rule match-type="regex"> + <from>^/stork2/ResumeAuthentication$</from> + <to type="forward">/dispatcher?mod=id_stork2&action=AttributeCollector&%{query-string}</to> + </rule> + <rule match-type="regex"> <from>^/stork2/SendPEPSAuthnRequest$</from> <to type="forward">/dispatcher?mod=id_stork2&action=AuthenticationRequest&%{query-string}</to> </rule> diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java index 8e7ca0779..d1de20c4d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java @@ -51,6 +51,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import at.gv.egovernment.moa.id.commons.db.dao.config.AttributeProviderPlugin; import at.gv.egovernment.moa.id.commons.db.dao.config.AuthComponentOA; import at.gv.egovernment.moa.id.commons.db.dao.config.BKUSelectionCustomizationType; import at.gv.egovernment.moa.id.commons.db.dao.config.BKUURLS; @@ -66,6 +67,7 @@ import at.gv.egovernment.moa.id.commons.db.dao.config.TemplatesType; import at.gv.egovernment.moa.id.commons.db.dao.config.TransformsInfoType; import at.gv.egovernment.moa.id.config.ConfigurationUtils; import at.gv.egovernment.moa.id.config.OAParameter; +import at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider; import at.gv.egovernment.moa.id.util.FormBuildUtils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; @@ -348,6 +350,9 @@ public List<OAStorkAttribute> getRequestedAttributes() { return oa_auth.getOASTORK().getOAAttributes(); } +public List<AttributeProviderPlugin> getStorkAPs() { + return oa_auth.getOASTORK().getAttributeProviders(); +} public byte[] getBKUSelectionTemplate() { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java index f79fd6e17..4dec2c32e 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java @@ -25,6 +25,7 @@ */
package at.gv.egovernment.moa.id.config.stork;
+import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -33,10 +34,15 @@ import java.util.List; import java.util.Map;
import java.util.Properties;
+import at.gv.egovernment.moa.id.commons.db.dao.config.SAMLSigningParameter;
import at.gv.egovernment.moa.id.commons.db.dao.config.STORK;
import at.gv.egovernment.moa.id.commons.db.dao.config.StorkAttribute;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.StringUtils;
+import org.opensaml.ws.message.encoder.MessageEncodingException;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.ParserConfigurationException;
/**
* Encapsulates several STORK configuration parameters according MOA configuration
@@ -59,7 +65,8 @@ public class STORKConfig { this.props = props;
//create CPEPS map
- List<at.gv.egovernment.moa.id.commons.db.dao.config.CPEPS> cpeps = null;
+ //List<at.gv.egovernment.moa.id.commons.db.dao.config.CPEPS> cpeps = stork.getCPEPS();
+ List<at.gv.egovernment.moa.id.commons.db.dao.config.CPEPS> cpeps = new ArrayList<at.gv.egovernment.moa.id.commons.db.dao.config.CPEPS>(); // TODO Change this
try {
cpeps = stork.getCPEPS();
@@ -82,20 +89,26 @@ public class STORKConfig { + cpep.getCountryCode() + " has an invalid URL and is ignored.");
}
}
+ /*catch (ParserConfigurationException e) {
+ Logger.warn("Error in MOA-ID Configuration. CPEP entry for country "
+ + cpep.getCountryCode() + " has an invalid Attribute and is ignored.");
+ } catch (SAXException e) {
+ Logger.warn("Error in MOA-ID Configuration. CPEP entry for country "
+ + cpep.getCountryCode() + " has an invalid Attribute and is ignored.");
+ } catch (IOException e) {
+ Logger.warn("Error in MOA-ID Configuration. CPEP entry for country "
+ + cpep.getCountryCode() + " has an invalid Attribute and is ignored.");
+ } catch (MessageEncodingException e) {
+ Logger.warn("Error in MOA-ID Configuration. CPEP entry for country "
+ + cpep.getCountryCode() + " has an invalid Attribute and is ignored.");
+ }*/
}
-
attr = new ArrayList<StorkAttribute>();
-
- try {
- if (stork.getAttributes() != null) {
+ if (stork.getAttributes() != null) {
for(StorkAttribute current : stork.getAttributes()) {
attr.add(current);
}
}
- } catch (NullPointerException ex) {
- Logger.error("Attributes not configured!");
-
- }
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java new file mode 100644 index 000000000..08244ab38 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java @@ -0,0 +1,196 @@ +package at.gv.egovernment.moa.id.protocols.stork2; + +import java.util.ArrayList; +import java.util.List; + +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +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.AuthConfigurationProvider; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +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.logging.Logger; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.opensaml.common.impl.SecureRandomIdentifierGenerator; + +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PersonalAttribute; + +/** + * 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 String processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, AuthenticationSession moasession) throws MOAIDException { + + // read configuration parameters of OA + OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(moasession.getPublicOAURLPrefix()); + if (oaParam == null) + throw new AuthenticationException("stork.12", new Object[] { moasession.getPublicOAURLPrefix() }); + + // find the attribute provider plugin that can handle the response + IPersonalAttributeList newAttributes = null; + for (AttributeProvider current : AttributeProviderFactory.getConfiguredPlugins(oaParam.getStorkAPs())) + try { + newAttributes = current.parse(httpReq); + } 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. + // TODO should we continue with the next attribute? + Logger.error("No attribute could be retrieved from the response the attribute provider gave us."); + throw new MOAIDException("stork.11", null); + } + + // - fetch the container + String artifactId = (String) httpReq.getAttribute(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); + } + + // - insert the embedded attribute(s) into the container + for(PersonalAttribute current : newAttributes) + container.getResponse().getPersonalAttributeList().add(current); + + // see if we need some more attributes + return processRequest(container, httpReq, httpResp, oaParam); + } + + /** + * 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 String processRequest(DataContainer container, HttpServletRequest request, HttpServletResponse response, 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>(); + for(PersonalAttribute current : requestAttributeList) + if(!responseAttributeList.containsKey(current)) + missingAttributes.add(current); + + try { + // for each attribute still missing + for(PersonalAttribute currentAttribute : missingAttributes) { + // - check if we can find a suitable AttributeProvider Plugin + for (AttributeProvider currentProvider : AttributeProviderFactory.getConfiguredPlugins(oaParam.getStorkAPs())) { + try { + // - hand over control to the suitable plugin + IPersonalAttributeList aquiredAttributes = currentProvider.acquire(currentAttribute); + + // - add the aquired attribute to the container + for(PersonalAttribute current : aquiredAttributes) + container.getResponse().getPersonalAttributeList().add(current); + } catch(UnsupportedAttributeException e) { + // ok, try the next attributeprovider + } + + } + } + } catch (ExternalAttributeRequestRequiredException e) { + // the attribute request is ongoing and requires an external service. + try { + // memorize the container again + // - generate new key + String newArtifactId = new SecureRandomIdentifierGenerator() + .generateIdentifier(); /* + Logger.debug("STORK QAA 2 :" + ((STORKAuthnRequestDEL) req).getStorkAuthnRequest().getQAALevel()); + StartAuthResponse startAuthResponse = getStartAuthResponse(((STORKAuthnRequestDEL) req).getStorkAuthnRequest()); + + HttpSession httpSession = httpReq.getSession(); + httpSession.setAttribute("STORKSessionID", "12345"); + httpResp.setStatus(startAuthResponse.getHttpStatusCode()); + try { + ServletOutputStream os = httpResp.getOutputStream(); + String html = new String(startAuthResponse.getContent()); + + + if (html.contains("<![CDATA[")) { + Logger.info("-------- content contains <![CDATA[-----------------"); + Logger.info("-------- content contains html -----------------"); + Logger.info("HTML : " + html); + int beginIndex = html.indexOf("<![CDATA["); + int endIndex = html.indexOf("]]>"); + html = html.substring(beginIndex + 9, endIndex); + startAuthResponse.setContent(html.getBytes()); + } + Logger.info("HTML : " + html); + + os.write(startAuthResponse.getContent()); + Logger.info("Response sent to client"); + } catch (IOException e) { + Logger.error("ERROR MOA"); + throw new MOAIDException("error response sending", new Object[]{}); + } + //httpSession.setAttribute("CCC", ccc); + + */ + } + + + //httpResp.setStatus(200); + //VPEPSInboundPostHandler + + // - put container in temporary store. + AssertionStorage.getInstance().put(newArtifactId, container); + + // add container-key to redirect embedded within the return URL + e.getAp().performRedirect(AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "?" + ARTIFACT_ID + "=" + newArtifactId, container.getRequest().getCitizenCountryCode(), 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", e); + throw new MOAIDException("stork.11", null); + } + + return "12345"; // TODO what to do here? + } + // build response + // done + return "12345"; // AssertionId + } + + /* (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/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeProvider.java new file mode 100644 index 000000000..adf57d77b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeProvider.java @@ -0,0 +1,52 @@ +package at.gv.egovernment.moa.id.protocols.stork2; + +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 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 interface AttributeProvider { + + /** + * Acquire the specified attribute. Returns {@code null} when attribute retrieval is in progress, but requires for + * for redirecting the user to an external service. Use {@link AttributeProvider#parse(HttpServletRequest)} to parse + * the response. + * + * @param attributes the list of attributes to be acquired + * @return the personal attribute + * @throws UnsupportedAttributeException the unsupported attribute exception + * @throws ExternalAttributeRequestRequiredException an attribute request to an external service has to be done + */ + public IPersonalAttributeList acquire(PersonalAttribute attributes) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException; + + /** + * Perform redirect. + * + * @param url the return URL ending with ?artifactId=... + * @param citizenCountyCode the citizen county code + * @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 + */ + public void performRedirect(String url, String citizenCountyCode, 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 IPersonalAttributeList parse(HttpServletRequest httpReq) throws UnsupportedAttributeException, MOAIDException; + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeProviderFactory.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeProviderFactory.java new file mode 100644 index 000000000..98d354e8a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeProviderFactory.java @@ -0,0 +1,57 @@ +package at.gv.egovernment.moa.id.protocols.stork2; + +import java.util.ArrayList; +import java.util.List; + +import at.gv.egovernment.moa.id.commons.db.dao.config.AttributeProviderPlugin; + +/** + * A factory for creating AttributeProvider objects. + */ +public class AttributeProviderFactory { + + /** + * Gets the available plugins. + * + * @return the available plugins + */ + public static List<String> getAvailablePlugins() { + List<String> result = new ArrayList<String>(); + result.add("StorkAttributeRequestProvider"); + + return result; + } + + /** + * 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) { + switch (shortname) { + case "StorkAttributeRequestProvider": + return new StorkAttributeRequestProvider(url); + default: + return null; + } + } + + /** + * Gets fresh instances of the configured plugins. + * + * @param configuredAPs the configured a ps + * @return the configured plugins + */ + public static List<AttributeProvider> getConfiguredPlugins( + List<AttributeProviderPlugin> configuredAPs) { + + List<AttributeProvider> result = new ArrayList<AttributeProvider>(); + for(AttributeProviderPlugin current : configuredAPs) + result.add(create(current.getName(), current.getUrl())); + + return result; + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java index 446d942ab..d742d72ef 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java @@ -5,6 +5,7 @@ import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.stork.VelocityProvider; 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.logging.Logger; import edu.emory.mathcs.backport.java.util.Collections; import eu.stork.peps.auth.commons.*; @@ -15,12 +16,18 @@ import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; - +import org.opensaml.xml.util.Base64; +import org.opensaml.xml.util.XMLHelper; +import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import java.io.*; -import java.util.ArrayList; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.HashMap; +import eu.stork.peps.auth.engine.SAMLEngine; /** @@ -90,6 +97,21 @@ public class AuthenticationRequest implements IAction { //httpResp.setStatus(200); //VPEPSInboundPostHandler + + // create fresh container + DataContainer container = new DataContainer(); + + // - fill in the request we extracted above + container.setRequest(request); + + // - fill in the partial response created above + container.setResponse(response); + + // - memorize the target url were we have to return the result + container.setTarget(target); + + // see if we need to fetch further attributes + return (new AttributeCollector()).processRequest(container); STORKAuthnResponse authnResponse = new STORKAuthnResponse(); @@ -244,7 +266,7 @@ public class AuthenticationRequest implements IAction { // moaAttributeProvider.populateAttribute(attributeList, "dateOfBirth"); - return attributeList; + return authResponse; } public String getDefaultActionName() { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DataContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DataContainer.java new file mode 100644 index 000000000..40c827ef8 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DataContainer.java @@ -0,0 +1,79 @@ +package at.gv.egovernment.moa.id.protocols.stork2; + +import java.io.Serializable; + +import eu.stork.peps.auth.commons.STORKAuthnRequest; +import eu.stork.peps.auth.commons.STORKAuthnResponse; + +// TODO: Auto-generated Javadoc +/** + * 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 STORKAuthnRequest request; + + /** The yet incomplete response. */ + private STORKAuthnResponse response; + + /** The target. */ + private String target; + + /** + * Gets the request. + * + * @return the request + */ + public STORKAuthnRequest getRequest() { + return request; + } + + /** + * Sets the request. + * + * @param request the new request + */ + public void setRequest(STORKAuthnRequest request) { + this.request = request; + } + + /** + * Gets the response. + * + * @return the response + */ + public STORKAuthnResponse getResponse() { + return response; + } + + /** + * Sets the response. + * + * @param response the new response + */ + public void setResponse(STORKAuthnResponse response) { + this.response = response; + } + + /** + * Gets the target. + * + * @return the target + */ + public String getTarget() { + return target; + } + + /** + * Sets the target. + * + * @param target the new target + */ + public void setTarget(String target) { + this.target = target; + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DemoNoRedirectAttributeProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DemoNoRedirectAttributeProvider.java new file mode 100644 index 000000000..e6f340c77 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DemoNoRedirectAttributeProvider.java @@ -0,0 +1,48 @@ +package at.gv.egovernment.moa.id.protocols.stork2; + +import java.util.ArrayList; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; + +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PersonalAttribute; +import eu.stork.peps.auth.commons.PersonalAttributeList; + +/** + * Just a simple demoprovider who can fetch any attribute you ask him. + */ +public class DemoNoRedirectAttributeProvider implements AttributeProvider { + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#acquire(java.lang.String) + */ + @Override + public IPersonalAttributeList acquire(PersonalAttribute attributeName) + throws UnsupportedAttributeException { + PersonalAttributeList requestedAttributes = new PersonalAttributeList(1); + requestedAttributes.add(new PersonalAttribute("sepp", true, new ArrayList<String>(), "")); + return requestedAttributes; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#parse(javax.servlet.http.HttpServletRequest) + */ + @Override + public IPersonalAttributeList parse(HttpServletRequest httpReq) { + // TODO Auto-generated method stub + return null; + } + + /* (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) + */ + @Override + public void performRedirect(String url, String citizenCountyCode, + HttpServletRequest req, HttpServletResponse resp, OAAuthParameter oaParam) { + // we should not get here + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DemoRedirectAttributeProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DemoRedirectAttributeProvider.java new file mode 100644 index 000000000..5d4336149 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/DemoRedirectAttributeProvider.java @@ -0,0 +1,48 @@ +package at.gv.egovernment.moa.id.protocols.stork2; + +import java.util.ArrayList; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; + +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PersonalAttribute; +import eu.stork.peps.auth.commons.PersonalAttributeList; + +/** + * Just a simple demoprovider who can fetch any attribute you ask him. + */ +public class DemoRedirectAttributeProvider implements AttributeProvider { + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#acquire(java.lang.String) + */ + @Override + public IPersonalAttributeList acquire(PersonalAttribute attributeName) + throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException { + throw new ExternalAttributeRequestRequiredException(this); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#parse(javax.servlet.http.HttpServletRequest) + */ + @Override + public IPersonalAttributeList parse(HttpServletRequest httpReq) { + PersonalAttributeList requestedAttributes = new PersonalAttributeList(1); + requestedAttributes.add(new PersonalAttribute("sepp", true, new ArrayList<String>(), "")); + return requestedAttributes; + } + + /* (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) + */ + @Override + public void performRedirect(String url, String citizenCountyCode, + HttpServletRequest req, HttpServletResponse resp, OAAuthParameter oaParam) { + // we should not get here + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ExternalAttributeRequestRequiredException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ExternalAttributeRequestRequiredException.java new file mode 100644 index 000000000..29b09487b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ExternalAttributeRequestRequiredException.java @@ -0,0 +1,14 @@ +package at.gv.egovernment.moa.id.protocols.stork2; + +public class ExternalAttributeRequestRequiredException extends Exception { + private AttributeProvider ap; + + public ExternalAttributeRequestRequiredException(AttributeProvider provider) { + ap = provider; + } + + public AttributeProvider getAp() { + return ap; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKProtocol.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKProtocol.java index 3d7852c4b..502925a2a 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKProtocol.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKProtocol.java @@ -34,12 +34,14 @@ public class STORKProtocol implements IModulInfo, MOAIDAuthConstants { public static final String PATH = "id_stork2"; public static final String AUTHENTICATIONREQUEST = "AuthenticationRequest"; + public static final String ATTRIBUTE_COLLECTOR = "AttributeCollector"; private static HashMap<String, IAction> actions = new HashMap<String, IAction>(); static { actions.put(AUTHENTICATIONREQUEST, new AuthenticationRequest()); + actions.put(ATTRIBUTE_COLLECTOR, new AttributeCollector()); instance = new STORKProtocol(); } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/StorkAttributeRequestProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/StorkAttributeRequestProvider.java new file mode 100644 index 000000000..3c689cac9 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/StorkAttributeRequestProvider.java @@ -0,0 +1,147 @@ +package at.gv.egovernment.moa.id.protocols.stork2; + +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.auth.stork.VelocityProvider; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.util.HTTPUtils; +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 implements AttributeProvider { + + private PersonalAttributeList requestedAttributes; + + /** The destination. */ + private String destination; + + /** + * Instantiates a new stork attribute request provider. + * + * @param apUrl the AP location + */ + public StorkAttributeRequestProvider(String apUrl) { + destination = apUrl; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#acquire(java.lang.String) + */ + @Override + public IPersonalAttributeList acquire(PersonalAttribute attribute) + throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException { + 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) + */ + @Override + public IPersonalAttributeList parse(HttpServletRequest httpReq) throws MOAIDException, UnsupportedAttributeException { + Logger.debug("Beginning 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 succesfully 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) + */ + @Override + public void performRedirect(String url, String citizenCountryCode, HttpServletRequest req, HttpServletResponse resp, OAAuthParameter oaParam) throws MOAIDException { + + String spSector = "Business"; + String spInstitution = StringUtils.isEmpty(oaParam.getFriendlyName()) ? "UNKNOWN" : oaParam.getFriendlyName(); + String spApplication = spInstitution; + String spCountry = "AT"; + + //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(spCountry); + attributeRequest.setSpApplication(spApplication); + attributeRequest.setSpSector(spSector); + attributeRequest.setPersonalAttributeList(requestedAttributes); + + attributeRequest.setCitizenCountryCode(citizenCountryCode); + + + Logger.debug("STORK AttrRequest succesfully assembled."); + + STORKSAMLEngine samlEngine = STORKSAMLEngine.getInstance("VIDP"); + try { + attributeRequest = samlEngine.generateSTORKAttrQueryRequest(attributeRequest); + } catch (STORKSAMLEngineException e) { + Logger.error("Could not sign STORK SAML AttrRequest.", e); + throw new MOAIDException("stork.00", null); + } + + Logger.info("STORK AttrRequest successfully signed!"); + + try { + Logger.trace("Initialize VelocityEngine..."); + + VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); + Template template = velocityEngine.getTemplate("/resources/templates/saml2-post-binding-moa.vm"); + VelocityContext context = new VelocityContext(); + context.put("SAMLRequest", PEPSUtil.encodeSAMLToken(attributeRequest.getTokenSaml())); + context.put("action", destination); + + StringWriter writer = new StringWriter(); + template.merge(context, writer); + + resp.getOutputStream().write(writer.toString().getBytes()); + } catch (Exception e) { + Logger.error("Error sending STORK SAML AttrRequest.", e); + throw new MOAIDException("stork.11", null); + } + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/UnsupportedAttributeException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/UnsupportedAttributeException.java new file mode 100644 index 000000000..9447c079f --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/UnsupportedAttributeException.java @@ -0,0 +1,7 @@ +package at.gv.egovernment.moa.id.protocols.stork2; + +public class UnsupportedAttributeException extends Exception { + + private static final long serialVersionUID = -7720066381435378111L; + +} diff --git a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties index 2559d3d18..0e252e981 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties @@ -205,6 +205,8 @@ stork.07=Es existiert kein STORK AuthnRequest f\u00FCr diese STORK Response stork.08=STORK SAML Assertion Validierung fehlgeschlagen
stork.09=Fehler beim \u00FCberpr\u00FCfen der STORK B\u00FCrgerInnen Signatur
stork.10=Fehler in der Verbindung zum SZR-Gateway
+stork.11=Fehler beim Sammeln von StorkAttributen
+stork.12=Konnte keine VIDP Konfiguration finden
pvp2.00={0} ist kein gueltiger consumer service index
pvp2.01=Fehler beim kodieren der PVP2 Antwort
diff --git a/id/server/moa-id-commons/src/main/resources/config/moaid_config_2.0.xsd b/id/server/moa-id-commons/src/main/resources/config/moaid_config_2.0.xsd index e6705dbb8..d20ec1c68 100644 --- a/id/server/moa-id-commons/src/main/resources/config/moaid_config_2.0.xsd +++ b/id/server/moa-id-commons/src/main/resources/config/moaid_config_2.0.xsd @@ -49,7 +49,7 @@ <xsd:extension base="xsd:string"/> </xsd:simpleContent> </xsd:complexType> - <xsd:element name="AbstractSimpleIdentification" type="StorkAttribute"> + <xsd:element name="AbstractSimpleIdentification" type="AttributeProviderPlugin"> <xsd:annotation> <xsd:documentation>possibility to include common austrian primary keys in human readable way, english translation not available @@ -884,6 +884,8 @@ <xsd:element name="StorkLogonEnabled" type="xsd:boolean"/> <xsd:element ref="Qaa" minOccurs="0" maxOccurs="1"/> <xsd:element ref="OAAttributes" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="VidpEnabled" type="xsd:boolean"></xsd:element> + <xsd:element ref="AttributeProviders" maxOccurs="unbounded" minOccurs="0"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> @@ -950,6 +952,15 @@ <xsd:element name="OnlyMandateLoginAllowed" type="xsd:boolean" default="false" minOccurs="0" maxOccurs="1"/> </xsd:sequence> </xsd:complexType> + + <xsd:complexType name="AttributeProviderPlugin"> + <xsd:sequence> + <xsd:element name="name" type="xsd:string"></xsd:element> + <xsd:element name="url" type="xsd:anyURI"></xsd:element> + </xsd:sequence> + </xsd:complexType> + + <xsd:element name="AttributeProviders" type="AttributeProviderPlugin"></xsd:element> <xsd:element name="Attributes" type="StorkAttribute"/> <xsd:element name="Qaa" type="QualityAuthenticationAssuranceLevelType"/> <xsd:complexType name="OAStorkAttribute"> |