diff options
Diffstat (limited to 'id/server/modules/module-stork/src/main/java/at')
2 files changed, 113 insertions, 48 deletions
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKProcessEngineSignalServlet.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKProcessEngineSignalServlet.java new file mode 100644 index 000000000..989f2b6bd --- /dev/null +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKProcessEngineSignalServlet.java @@ -0,0 +1,113 @@ +package at.gv.egovernment.moa.id.auth.modules.stork;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.bouncycastle.util.encoders.Base64;
+import org.springframework.util.xml.SimpleNamespaceContext;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.servlet.ProcessEngineSignalServlet;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * STORK module specific servlet, overloading {@link ProcessEngineSignalServlet}'s method
+ * {@linkplain ProcessEngineSignalServlet#getMoaSessionId(HttpServletRequest) getMoaSessionId(HttpServletRequest)}
+ * extending its capabilities for retrieving the current moa session id.
+ * <p/>
+ * This {@code STORKProcessEngineSignalServlet} tries to resolve the moa session id using the following strategy:
+ * <ul>
+ * <li>Use the super class' approach, looking at the HttpServletRequest parameter
+ * {@link MOAIDAuthConstants#PARAM_SESSIONID}.</li>
+ * <li>Evaluate the request parameter "{@code RelayState}".
+ * <li>Finally evaluate the SAML response, which should come base64 encoded as request parameter "{@code SAMLResponse}".</li>
+ * </ul>
+ *
+ * @author tknall
+ *
+ */
+@WebServlet(urlPatterns = { "/PEPSConnectorWithLocalSigning", "/PEPSConnector" }, loadOnStartup = 1)
+public class STORKProcessEngineSignalServlet extends ProcessEngineSignalServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ public STORKProcessEngineSignalServlet() {
+ super();
+ Logger.debug("Registering servlet " + getClass().getName() + " with mappings '/PEPSConnectorWithLocalSigning', '/PEPSConnector'.");
+ }
+
+ @Override
+ public String getMoaSessionId(HttpServletRequest request) {
+ String sessionId = super.getMoaSessionId(request);
+
+ try {
+
+ // use SAML2 relayState
+ if (sessionId == null) {
+ sessionId = StringEscapeUtils.escapeHtml(request.getParameter("RelayState"));
+ }
+
+ // take from InResponseTo attribute of SAMLResponse
+ if (sessionId == null) {
+ String base64SamlToken = request.getParameter("SAMLResponse");
+ if (base64SamlToken != null) {
+ byte[] samlToken = Base64.decode(base64SamlToken);
+ Document samlResponse = parseDocument(new ByteArrayInputStream(samlToken));
+
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
+ nsContext.bindNamespaceUri("saml2p", "urn:oasis:names:tc:SAML:2.0:protocol");
+ xPath.setNamespaceContext(nsContext);
+ XPathExpression expression = xPath.compile("string(/saml2p:Response/@InResponseTo)");
+ sessionId = (String) expression.evaluate(samlResponse, XPathConstants.STRING);
+ sessionId = StringEscapeUtils.escapeHtml(StringUtils.trimToNull(sessionId));
+ } else {
+ Logger.warn("No parameter 'SAMLResponse'. Unable to retrieve MOA session id.");
+ }
+ }
+
+ } catch (Exception e) {
+ Logger.warn("Unable to retrieve moa session id.", e);
+ }
+
+ return sessionId;
+ }
+
+ /**
+ * Parses a xml document (namespace aware).
+ *
+ * @param in
+ * The input stream.
+ * @return The DOM document.
+ * @throws ParserConfigurationException
+ * Thrown in case of configuration error.
+ * @throws IOException
+ * Thrown in case of error reading from the input stream.
+ * @throws SAXException
+ * Thrown in case of error parsing the document.
+ */
+ public static Document parseDocument(InputStream in) throws ParserConfigurationException, SAXException, IOException {
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setNamespaceAware(true);
+ documentBuilderFactory.setIgnoringElementContentWhitespace(false);
+ documentBuilderFactory.setValidating(false);
+ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ return documentBuilder.parse(in);
+ }
+
+}
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKWebApplicationInitializer.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKWebApplicationInitializer.java deleted file mode 100644 index c54c9a26d..000000000 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKWebApplicationInitializer.java +++ /dev/null @@ -1,48 +0,0 @@ -package at.gv.egovernment.moa.id.auth.modules.stork;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRegistration;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.WebApplicationInitializer;
-
-import at.gv.egovernment.moa.id.auth.servlet.ProcessEngineSignalServlet;
-
-/**
- * Spring automatically discovers {@link WebApplicationInitializer} implementations at startup.<br/>
- * This STORK webapp initializer adds the required servlet mappings:
- * <ul>
- * <li>{@code /PEPSConnector}</li>
- * <li>{@code /PEPSConnectorWithLocalSigning}</li>
- * </ul>
- * for the {@linkplain ProcessEngineSignalServlet process engine servlet} (named {@code ProcessEngineSignal}) that wakes
- * up a process in order to execute asynchronous tasks. Therefore the servlet mappings mentioned above do not need to be
- * declared in {@code web.xml}.
- *
- * @author tknall
- * @see ProcessEngineSignalServlet
- */
-public class STORKWebApplicationInitializer implements WebApplicationInitializer {
-
- private Logger log = LoggerFactory.getLogger(getClass());
-
- private static final String SIGNAL_SERVLET_NAME = "ProcessEngineSignal";
-
- private void addMapping(ServletRegistration servletRegistration, String mapping) {
- log.debug("Adding mapping '{}' to servlet '{}' ({}).", mapping, SIGNAL_SERVLET_NAME, servletRegistration.getClassName());
- servletRegistration.addMapping(mapping);
- }
-
- @Override
- public void onStartup(ServletContext servletContext) throws ServletException {
- ServletRegistration servletRegistration = servletContext.getServletRegistration(SIGNAL_SERVLET_NAME);
- if (servletRegistration == null) {
- throw new IllegalStateException("Servlet '" + SIGNAL_SERVLET_NAME + "' expected to be registered (e.g. by web.xml).");
- }
- addMapping(servletRegistration, "/PEPSConnectorWithLocalSigning");
- addMapping(servletRegistration, "/PEPSConnector");
- }
-
-}
|