package at.gv.egovernment.moa.id.auth.tasks;
import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.GET_MIS_SESSIONID;
import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.PARAM_SESSIONID;
import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.PARAM_XMLRESPONSE;
import iaik.pki.PKIException;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.List;
import java.util.Map;
import javax.net.ssl.SSLSocketFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.TransformerException;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.lang.StringEscapeUtils;
import org.w3c.dom.Element;
import at.gv.egovernment.moa.id.auth.AuthenticationServer;
import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
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.MISSimpleClientException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.config.ConnectionParameter;
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.ModulUtils;
import at.gv.egovernment.moa.id.process.api.ExecutionContext;
import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
import at.gv.egovernment.moa.id.util.SSLUtils;
import at.gv.egovernment.moa.id.util.client.mis.simple.MISSessionId;
import at.gv.egovernment.moa.id.util.client.mis.simple.MISSimpleClient;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.DOMUtils;
/**
* Verifies the signed authentication block (provided as {@code CreateXMLSignatureResponse}).
* In detail:
*
* - Renames the moa session id.
* - Takes the {@code CreateXMLSignatureResponse} from POST parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE}.
* - Verifies the {@code CreateXMLSignatureResponse}.
* - Updates moa session.
* - Redirects back to {@code /dispatcher} in order to finalize the authentication.
*
* Expects:
*
* - HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_SESSIONID}
* - HttpServletRequest parameter {@link MOAIDAuthConstants#PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.
*
* Result:
*
* - Authentication data put into moa session.
* - Redirect to {@code /dispatcher}.
*
* Possible branches:
*
* - In case of mandate mode
*
* - Creates a mandate session at the external mandate issuing service.
* - Redirects the user's browser to the online mandate issuing service GUI.
*
*
*
* Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet}.
* @author tknall
* @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
*
*/
public class VerifyAuthenticationBlockTask extends AbstractAuthServletTask {
@Override
public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
throws Exception {
// note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet
Logger.debug("POST VerifyAuthenticationBlock");
String pendingRequestID = null;
Map parameters;
try
{
parameters = getParameters(req);
} catch (FileUploadException e)
{
Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
throw new IOException(e.getMessage());
}
String sessionID = req.getParameter(PARAM_SESSIONID);
String createXMLSignatureResponse = (String)parameters.get(PARAM_XMLRESPONSE);
// escape parameter strings
sessionID = StringEscapeUtils.escapeHtml(sessionID);
pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
String redirectURL = null;
try {
// check parameter
if (!ParamValidatorUtils.isValidSessionID(sessionID))
throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID, "auth.12");
if (!ParamValidatorUtils.isValidXMLDocument(createXMLSignatureResponse))
throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_XMLRESPONSE, "auth.12");
AuthenticationSession session = AuthenticationServer.getSession(sessionID);
//change MOASessionID
sessionID = AuthenticationSessionStoreage.changeSessionID(session);
String authenticatedMOASessionId = AuthenticationServer.getInstance().verifyAuthenticationBlock(session, createXMLSignatureResponse);
if (authenticatedMOASessionId == null) {
//mandate Mode
AuthConfigurationProvider authConf= AuthConfigurationProvider.getInstance();
ConnectionParameter connectionParameters = authConf.getOnlineMandatesConnectionParameter();
SSLSocketFactory sslFactory = SSLUtils.getSSLSocketFactory(AuthConfigurationProvider.getInstance(), connectionParameters);
// get identitity link as byte[]
Element elem = session.getIdentityLink().getSamlAssertion();
String s = DOMUtils.serializeNode(elem);
//System.out.println("IDL: " + s);
byte[] idl = s.getBytes("UTF-8");
// redirect url
// build redirect(to the GetMISSessionIdSerlvet)
//change MOASessionID before MIS request
String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
redirectURL =
new DataURLBuilder().buildDataURL(
session.getAuthURL(),
GET_MIS_SESSIONID,
newMOASessionID);
String oaURL = session.getOAURLRequested();
OAAuthParameter oaParam = authConf.getOnlineApplicationParameter(oaURL);
List profiles = oaParam.getMandateProfiles();
if (profiles == null) {
Logger.error("No Mandate/Profile for OA configured.");
throw new AuthenticationException("config.21", new Object[] { GET_MIS_SESSIONID});
}
String oaFriendlyName = oaParam.getFriendlyName();
String mandateReferenceValue = session.getMandateReferenceValue();
byte[] cert = session.getEncodedSignerCertificate();
byte[] authBlock = session.getAuthBlock().getBytes("UTF-8");
//TODO: check in case of SSO!!!
String targetType = null;
if(oaParam.getBusinessService()) {
String id = oaParam.getIdentityLinkDomainIdentifier();
if (id.startsWith(AuthenticationSession.REGISTERANDORDNR_PREFIX_))
targetType = id;
else
targetType = AuthenticationSession.REGISTERANDORDNR_PREFIX_+session.getDomainIdentifier();
} else {
targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
}
MISSessionId misSessionID = MISSimpleClient.sendSessionIdRequest(
connectionParameters.getUrl(),
idl,
cert,
oaFriendlyName,
redirectURL,
mandateReferenceValue,
profiles,
targetType,
authBlock,
sslFactory);
if (misSessionID == null) {
Logger.error("Fehler bei Anfrage an Vollmachten Service. MIS Session ID ist null.");
throw new MISSimpleClientException("Fehler bei Anfrage an Vollmachten Service.");
}
String redirectMISGUI = misSessionID.getRedirectURL();
session.setMISSessionID(misSessionID.getSessiondId());
try {
AuthenticationSessionStoreage.storeSession(session);
} catch (MOADatabaseException e) {
throw new MOAIDException("Session store error", null);
}
// TODO[branch]: Mandate; redirect to MIS website; website redirects back to "/GetMISSessionID"
resp.setStatus(302);
resp.addHeader("Location", redirectMISGUI);
Logger.debug("REDIRECT TO: " + redirectURL);
}
else {
// TODO[branch]: Final step back to /dispatcher
redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(),
ModulUtils.buildAuthURL(session.getModul(), session.getAction(), pendingRequestID), authenticatedMOASessionId);
resp.setContentType("text/html");
resp.setStatus(302);
resp.addHeader("Location", redirectURL);
Logger.debug("REDIRECT TO: " + redirectURL);
}
}
catch (MOAIDException ex) {
handleError(null, ex, req, resp, pendingRequestID);
} catch (GeneralSecurityException e) {
handleError(null, e, req, resp, pendingRequestID);
} catch (PKIException e) {
handleError(null, e, req, resp, pendingRequestID);
} catch (TransformerException e) {
handleError(null, e, req, resp, pendingRequestID);
} catch (Exception e) {
Logger.error("AuthBlockValidation has an interal Error.", e);
}
finally {
ConfigurationDBUtils.closeSession();
}
}
}