aboutsummaryrefslogtreecommitdiff
path: root/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv
diff options
context:
space:
mode:
authorThomas Lenz <tlenz@iaik.tugraz.at>2016-02-18 19:21:10 +0100
committerThomas Lenz <tlenz@iaik.tugraz.at>2016-02-18 19:21:10 +0100
commit9bafb2671b297d39574c346c896347f197282081 (patch)
tree6a6b4a0a3327990e10e99395764eb80a2aea2e24 /id/server/modules/moa-id-modules-saml1/src/main/java/at/gv
parentf38bf93a9636f43246b7021c0ac48591b7afaf57 (diff)
downloadmoa-id-spss-9bafb2671b297d39574c346c896347f197282081.tar.gz
moa-id-spss-9bafb2671b297d39574c346c896347f197282081.tar.bz2
moa-id-spss-9bafb2671b297d39574c346c896347f197282081.zip
remove AXIS1 implemented WebService for SAML1 --> now a simple Spring controller is used as WebService endpoint
Diffstat (limited to 'id/server/modules/moa-id-modules-saml1/src/main/java/at/gv')
-rw-r--r--id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetAuthenticationDataService.java386
-rw-r--r--id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AssertionResponseBuildException.java86
2 files changed, 345 insertions, 127 deletions
diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetAuthenticationDataService.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetAuthenticationDataService.java
index 7e46e53fe..fc5837e51 100644
--- a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetAuthenticationDataService.java
+++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetAuthenticationDataService.java
@@ -46,18 +46,39 @@
package at.gv.egovernment.moa.id.protocols.saml1;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
import java.util.Calendar;
-import org.apache.axis.AxisFault;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
import at.gv.egovernment.moa.id.auth.builder.SAMLResponseBuilder;
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.servlet.AbstractController;
import at.gv.egovernment.moa.id.util.ErrorResponseUtils;
+import at.gv.egovernment.moa.id.util.HTTPUtils;
import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
import at.gv.egovernment.moa.id.util.Random;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
+import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.Constants;
import at.gv.egovernment.moa.util.DOMUtils;
import at.gv.egovernment.moa.util.DateTimeUtils;
@@ -66,151 +87,262 @@ import at.gv.egovernment.moa.util.XPathUtils;
/**
* Web service for picking up authentication data created in the MOA-ID Auth component.
*
- * @author Paul Ivancsics
- * @version $Id: GetAuthenticationDataService.java 1233 2012-01-26 21:59:33Z kstranacher $
- * @see at.gv.egovernment.moa.id.auth.AuthenticationServer#getAuthenticationData
+ * This getAssertion WebService implementations a hacked solution to integrate SAML1 into
+ * the new Spring based MOA-ID implementation.
+ *
+ * @deprecated
+ * It is too bad about the time to implement a better solution,
+ * since SAML1 is deprecated MOA-ID >= 2.0.0
+ *
+ * @author tlenz
*/
-public class GetAuthenticationDataService implements Constants {
+@Controller
+public class GetAuthenticationDataService extends AbstractController implements Constants {
- /**
- * Constructor for GetAuthenticationDataService.
- */
- public GetAuthenticationDataService() {
- super();
- }
+ @Autowired private SAML1AuthenticationServer saml1AuthServer;
+
+ private static final String PARAM_WSDL="wsdl";
+ private static final String PARAM_XSD="xsd";
+
+ private static final String TEMPLATE_PLAIN_INFO="plain_info.vm";
+ private static final String TEMPLATE_WSDL="wsdl/MOA-ID-1.x.vm";
+ private static final String TEMPLATE_XSD="wsdl/MOA-SPSS-1.2.vm";
+ private static final String TEMPLATE_SOAP_ERROR="soap_error.vm";
+ private static final String TEMPLATE_SOAP_SUCCESS="soap_success.vm";
+
+ private static final String SERVICE_ENDPOINT = "/services/GetAuthenticationData";
+
+ private static final String CONTEXT_ENDPOINT = "endpoint";
+ private static final String CONTEXT_ERROR = "error";
+
+ private static final String CONTEXT_SOAP_RESPONSEID = "responseID";
+ private static final String CONTEXT_SOAP_REQUESTEID = "requestID";
+ private static final String CONTEXT_SOAP_ISSUEINSTANT = "issueInstant";
+ private static final String CONTEXT_SOAP_ERRORMESSAGE = "errorMsg";
+ private static final String CONTEXT_SOAP_STATUSCODE = "statusCode";
+ private static final String CONTEXT_SOAP_ASSERTION = "assertion";
+
+ @RequestMapping(value = "/services/GetAuthenticationData", method = {RequestMethod.POST})
+ public void getAuthenticationData(HttpServletRequest req, HttpServletResponse resp)
+ throws IOException {
+ InputStream is = null;
+ VelocityContext context = new VelocityContext();
+ try {
+ is = req.getInputStream();
+ Element soapReq = DOMUtils.parseXmlNonValidating(is);
- /**
- * Takes a <code>lt;samlp:Request&gt;</code> containing a
- * <code>SAML artifact</code> and returns the corresponding
- * authentication data <code>lt;saml:Assertion&gt;</code>
- * (obtained from the <code>AuthenticationServer</code>),
- * enclosed in a <code>lt;samlp:Response&gt;</code>.
- * <br/>Bad requests are mapped into various <code>lt;samlp:StatusCode&gt;</code>s,
- * possibly containing enclosed sub-<code>lt;samlp:StatusCode&gt;</code>s.
- * The status codes are defined in the SAML specification.
- *
- * @param requests request elements of type <code>lt;samlp:Request&gt;</code>;
- * only 1 request element is allowed
- * @return response element of type <code>lt;samlp:Response&gt;</code>,
- * packed into an <code>Element[]</code>
- * @throws AxisFault thrown when an error occurs in assembling the
- * <code>lt;samlp:Response&gt;</code>
- */
- public Element[] Request(Element[] requests)
- throws AxisFault {
-
- Element request = requests[0];
- Element[] responses = new Element[1];
+ //process request
+ Element soapResp = processRequest(soapReq);
+
+ String respString = DOMUtils.serializeNode(soapResp, true);
+
+ resp.setContentType("text/xml;charset=UTF-8");
+ context.put(CONTEXT_SOAP_ASSERTION, respString);
+ evaluateTemplate(context, resp, TEMPLATE_SOAP_SUCCESS);
+
+ } catch (ParserConfigurationException | SAXException | IOException | TransformerException e) {
+ Logger.error("SAML1 GetAuthenticationData receive a non-valid request.", e);
+ resp.setContentType("text/xml;charset=UTF-8");
+
+ context.put(CONTEXT_SOAP_ISSUEINSTANT, DateTimeUtils.buildDateTimeUTC(Calendar.getInstance()));
+ context.put(CONTEXT_SOAP_RESPONSEID, Random.nextRandom());
+ context.put(CONTEXT_SOAP_STATUSCODE, "samlp:Requester");
+ context.put(CONTEXT_SOAP_ERRORMESSAGE, e.getMessage());
+
+ evaluateTemplate(context, resp, TEMPLATE_SOAP_ERROR);
+
+ } catch (SAML1AssertionResponseBuildException e) {
+ Logger.error("SAML1 GetAuthenticationData response build failed..", e);
+ resp.setContentType("text/xml;charset=UTF-8");
+
+ context.put(CONTEXT_SOAP_ISSUEINSTANT, e.getIssueInstant());
+ context.put(CONTEXT_SOAP_REQUESTEID, e.getRequestID());
+ context.put(CONTEXT_SOAP_RESPONSEID, e.getResponseID());
+ context.put(CONTEXT_SOAP_STATUSCODE, "samlp:Responder");
+ context.put(CONTEXT_SOAP_ERRORMESSAGE, e.getMessage());
+
+ evaluateTemplate(context, resp, TEMPLATE_SOAP_ERROR);
+
+ } finally {
+ try {
+ if (is != null)
+ is.close();
+
+ } catch (Exception e) {
+
+ }
+ }
+ }
+
+ @RequestMapping(value = "/services/GetAuthenticationData", method = {RequestMethod.GET})
+ public void getAuthenticationDataWSDL(HttpServletRequest req, HttpServletResponse resp)
+ throws Exception {
+ String wsdl_param = req.getParameter(PARAM_WSDL);
+ String xsd_param = req.getParameter(PARAM_XSD);
+
+ String fullServiceEndPoint = HTTPUtils.extractAuthURLFromRequest(req) + SERVICE_ENDPOINT;
+
+ VelocityContext context = new VelocityContext();
+ context.put(CONTEXT_ENDPOINT, fullServiceEndPoint);
+
+ if (wsdl_param != null) {
+ //print wsdl
+ resp.setContentType("text/xml;charset=UTF-8");
+ evaluateTemplate(context, resp, TEMPLATE_WSDL);
+
+ } else if (xsd_param != null){
+ //print xsd
+ resp.setContentType("text/xml;charset=UTF-8");
+ evaluateTemplate(context, resp, TEMPLATE_XSD);
+
+ } else {
+ //print plain info
+ resp.setContentType("text/html;charset=UTF-8");
+ evaluateTemplate(context, resp, TEMPLATE_PLAIN_INFO);
+
+ }
+
+ }
+
+ private Element processRequest(Element soapReq) throws ParserConfigurationException, IOException, SAXException, TransformerException, SAML1AssertionResponseBuildException {
String requestID = "";
String statusCode = "";
String subStatusCode = null;
String statusMessageCode = null;
String statusMessage = null;
String samlAssertion = "";
- if (requests.length > 1) {
- // more than 1 request given as parameter
- statusCode = "samlp:Requester";
- subStatusCode = "samlp:TooManyResponses";
- statusMessageCode = "1201";
- }
+ Element responses;
+
+ //select soap-body element
+ NodeList saml1ReqList = soapReq.getElementsByTagNameNS(soapReq.getNamespaceURI(), "Body");;
+ if (saml1ReqList.getLength() != 1) {
+ saml1ReqList = soapReq.getElementsByTagNameNS(soapReq.getNamespaceURI(), "body");;
+ if (saml1ReqList.getLength() != 1) {
+ throw new SAXException("No unique 'soap-env:Body' element.");
+
+ }
+ }
+
+ //get first child from body --> should be the SAML1 Request element
+ Element saml1Req;
+ if (saml1ReqList.item(0).getFirstChild() instanceof Element)
+ saml1Req = (Element) saml1ReqList.item(0).getFirstChild();
+
else {
- try {
- DOMUtils.validateElement(request, ALL_SCHEMA_LOCATIONS, null);
- NodeList samlArtifactList = XPathUtils.selectNodeList(request, "samlp:AssertionArtifact");
- if (samlArtifactList.getLength() == 0) {
- // no SAML artifact given in request
- statusCode = "samlp:Requester";
- statusMessageCode = "1202";
- }
- else if (samlArtifactList.getLength() > 1) {
- // too many SAML artifacts given in request
- statusCode = "samlp:Requester";
- subStatusCode = "samlp:TooManyResponses";
- statusMessageCode = "1203";
- }
+ throw new SAXException("First child of 'soap-env:Body' element has a wrong type.");
- else {
- Element samlArtifactElem = (Element)samlArtifactList.item(0);
- requestID = request.getAttribute("RequestID");
- String samlArtifact = DOMUtils.getText(samlArtifactElem);
-
-
- //SAML1AuthenticationServer saml1server = SAML1AuthenticationServer.getInstace();
-
- try {
+ }
- samlAssertion = "Find a solution to integrate Axis 1 into Spring";
- //samlAssertion = saml1server.getSaml1AuthenticationData(samlArtifact);
-
- // success
- statusCode = "samlp:Success";
- statusMessageCode = "1200";
- }
-
- catch (ClassCastException ex) {
+ //validate the SAML1 request element, which we selected above
+ DOMUtils.validateElement(saml1Req, ALL_SCHEMA_LOCATIONS, null);
+
+ //parse inforamtion from SAML1 request
+ try {
+ NodeList samlArtifactList = XPathUtils.selectNodeList(saml1Req, "samlp:AssertionArtifact");
+ if (samlArtifactList.getLength() == 0) {
+ // no SAML artifact given in request
+ statusCode = "samlp:Requester";
+ statusMessageCode = "1202";
+
+ } else if (samlArtifactList.getLength() > 1) {
+ // too many SAML artifacts given in request
+ statusCode = "samlp:Requester";
+ subStatusCode = "samlp:TooManyResponses";
+ statusMessageCode = "1203";
+
+ } else {
+ Element samlArtifactElem = (Element)samlArtifactList.item(0);
+ requestID = saml1Req.getAttribute("RequestID");
+ String samlArtifact = DOMUtils.getText(samlArtifactElem);
+
+ try {
+ samlAssertion = saml1AuthServer.getSaml1AuthenticationData(samlArtifact);
+
+ // success
+ statusCode = "samlp:Success";
+ statusMessageCode = "1200";
- try {
- //Throwable error = saml1server.getErrorResponse(samlArtifact);
- Throwable error = new Exception("Find a solution to integrate Axis 1 into Spring");
- statusCode = "samlp:Responder";
+ } catch (ClassCastException ex) {
+ try {
+ Throwable error = saml1AuthServer.getErrorResponse(samlArtifact);
+ statusCode = "samlp:Responder";
+
+ ErrorResponseUtils errorUtils = ErrorResponseUtils.getInstance();
+
+ if (error instanceof MOAIDException) {
+ statusMessageCode = ((MOAIDException)error).getMessageId();
+ statusMessage = StringEscapeUtils.escapeXml(((MOAIDException)error).getMessage());
- ErrorResponseUtils errorUtils = ErrorResponseUtils.getInstance();
+ } else {
+ statusMessage = StringEscapeUtils.escapeXml(error.getMessage());
- if (error instanceof MOAIDException) {
- statusMessageCode = ((MOAIDException)error).getMessageId();
- statusMessage = StringEscapeUtils.escapeXml(((MOAIDException)error).getMessage());
-
- } else {
- statusMessage = StringEscapeUtils.escapeXml(error.getMessage());
- }
- subStatusCode = errorUtils.getResponseErrorCode(error);
-
- } catch (Exception e) {
- //no authentication data for given SAML artifact
- statusCode = "samlp:Requester";
- subStatusCode = "samlp:ResourceNotRecognized";
- statusMessage = ex.toString();
- }
-
+ }
+ subStatusCode = errorUtils.getResponseErrorCode(error);
+
+ } catch (Exception e) {
+ //no authentication data for given SAML artifact
+ statusCode = "samlp:Requester";
+ subStatusCode = "samlp:ResourceNotRecognized";
+ statusMessage = ex.toString();
}
-// catch (AuthenticationException ex) {
-// //no authentication data for given SAML artifact
-// statusCode = "samlp:Requester";
-// subStatusCode = "samlp:ResourceNotRecognized";
-// statusMessage = ex.toString();
-// }
+ } catch (AuthenticationException ex) {
+ //no authentication data for given SAML artifact
+ statusCode = "samlp:Requester";
+ subStatusCode = "samlp:ResourceNotRecognized";
+ statusMessage = ex.toString();
}
}
- catch (Throwable t) {
- // invalid request format
- statusCode = "samlp:Requester";
- statusMessageCode = "1204";
- }
+
+
+ } catch (Throwable t) {
+ // invalid request format
+ statusCode = "samlp:Requester";
+ statusMessageCode = "1204";
+
+ }
+
+ String responseID = Random.nextRandom();
+ String issueInstant = DateTimeUtils.buildDateTimeUTC(Calendar.getInstance());
+
+ try {
+ if (statusMessage == null)
+ statusMessage = MOAIDMessageProvider.getInstance().getMessage(statusMessageCode, null);
+ responses = new SAMLResponseBuilder().build(
+ responseID, requestID, issueInstant, statusCode, subStatusCode, statusMessage, samlAssertion);
+ return responses;
+
+ } catch (Throwable e) {
+ throw new SAML1AssertionResponseBuildException(responseID, issueInstant,
+ requestID, "1299", e.getMessage(), e);
+
+ }
}
+
+
+ private void evaluateTemplate(VelocityContext context, HttpServletResponse httpResp, String templateURL) throws IOException {
+ InputStream is = null;
+ try {
+ is = Thread.currentThread()
+ .getContextClassLoader()
+ .getResourceAsStream(templateURL);
+
+ VelocityEngine engine = VelocityProvider.getClassPathVelocityEngine();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is ));
+ StringWriter writer = new StringWriter();
+ engine.evaluate(context, writer, "SAML1 GetAuthenticationData", reader);
+ httpResp.getOutputStream().write(writer.toString().getBytes("UTF-8"));
+
+ } catch (Exception e) {
+ Logger.error("SAML1 GetAuthenticationData has an error:", e);
+ throw new IOException(e);
+
+ } finally {
+ if (is != null)
+ is.close();
+
+ }
- try {
- String responseID = Random.nextRandom();
- String issueInstant = DateTimeUtils.buildDateTimeUTC(Calendar.getInstance());
-
- if (statusMessage == null)
- statusMessage = MOAIDMessageProvider.getInstance().getMessage(statusMessageCode, null);
- responses[0] = new SAMLResponseBuilder().build(
- responseID, requestID, issueInstant, statusCode, subStatusCode, statusMessage, samlAssertion);
-
- }
- catch (MOAIDException e) {
- AxisFault fault = AxisFault.makeFault(e);
- fault.setFaultDetail(new Element[] { e.toErrorResponse()});
- throw fault;
- }
- catch (Throwable t) {
- MOAIDException e = new MOAIDException("1299", null, t);
- AxisFault fault = AxisFault.makeFault(e);
- fault.setFaultDetail(new Element[] { e.toErrorResponse()});
- throw fault;
- }
- return responses;
- }
-
+ }
}
+
diff --git a/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AssertionResponseBuildException.java b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AssertionResponseBuildException.java
new file mode 100644
index 000000000..0c06a94df
--- /dev/null
+++ b/id/server/modules/moa-id-modules-saml1/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AssertionResponseBuildException.java
@@ -0,0 +1,86 @@
+/*
+ * 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.saml1;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SAML1AssertionResponseBuildException extends Exception {
+
+ private static final long serialVersionUID = -394698807368683821L;
+
+ private String responseID;
+ private String issueInstant;
+ private String requestID;
+ private String errorCode;
+
+ /**
+ * @param responseID
+ * @param issueInstant
+ * @param requestID
+ * @param string
+ * @param message
+ */
+ public SAML1AssertionResponseBuildException(String responseID, String issueInstant, String requestID, String errorCode,
+ String errorMsg, Throwable throwable) {
+ super(errorMsg, throwable);
+
+ this.requestID = requestID;
+ this.issueInstant = issueInstant;
+ this.responseID = responseID;
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * @return the responseID
+ */
+ public String getResponseID() {
+ return responseID;
+ }
+
+ /**
+ * @return the issueInstant
+ */
+ public String getIssueInstant() {
+ return issueInstant;
+ }
+
+ /**
+ * @return the requestID
+ */
+ public String getRequestID() {
+ return requestID;
+ }
+
+ /**
+ * @return the errorCode
+ */
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+
+
+
+}