package at.gv.egovernment.moa.id.auth.servlet;
import java.util.Calendar;
import org.apache.axis.AxisFault;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import at.gv.egovernment.moa.id.AuthenticationException;
import at.gv.egovernment.moa.id.MOAIDException;
import at.gv.egovernment.moa.id.auth.AuthenticationServer;
import at.gv.egovernment.moa.id.auth.builder.SAMLResponseBuilder;
import at.gv.egovernment.moa.id.data.AuthenticationData;
import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
import at.gv.egovernment.moa.id.util.Random;
import at.gv.egovernment.moa.util.Constants;
import at.gv.egovernment.moa.util.DOMUtils;
import at.gv.egovernment.moa.util.DateTimeUtils;
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$
* @see at.gv.egovernment.moa.id.auth.AuthenticationServer#getAuthenticationData
*/
public class GetAuthenticationDataService implements Constants {
/**
* Constructor for GetAuthenticationDataService.
*/
public GetAuthenticationDataService() {
super();
}
/**
* Takes a lt;samlp:Request>
containing a
* SAML artifact
and returns the corresponding
* authentication data lt;saml:Assertion>
* (obtained from the AuthenticationServer
),
* enclosed in a lt;samlp:Response>
.
*
Bad requests are mapped into various lt;samlp:StatusCode>
s,
* possibly containing enclosed sub-lt;samlp:StatusCode>
s.
* The status codes are defined in the SAML specification.
*
* @param requests request elements of type lt;samlp:Request>
;
* only 1 request element is allowed
* @return response element of type lt;samlp:Response>
,
* packed into an Element[]
* @throws AxisFault thrown when an error occurs in assembling the
* lt;samlp:Response>
*/
public Element[] Request(Element[] requests)
throws AxisFault {
Element request = requests[0];
Element[] responses = new Element[1];
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";
}
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";
}
else {
Element samlArtifactElem = (Element)samlArtifactList.item(0);
requestID = samlArtifactElem.getAttribute("RequestID");
String samlArtifact = DOMUtils.getText(samlArtifactElem);
try {
AuthenticationData authData = AuthenticationServer.getInstance().
getAuthenticationData(samlArtifact);
// success
samlAssertion = authData.getSamlAssertion();
statusCode = "samlp:Success";
statusMessageCode = "1200";
}
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";
}
}
try {
String responseID = Random.nextRandom();
String issueInstant = DateTimeUtils.buildDateTime(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;
}
}