at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorWithLocalSigningServlet.java Source code

Java tutorial

Introduction

Here is the source code for at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorWithLocalSigningServlet.java

Source

/*******************************************************************************
 * 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.auth.servlet;

import iaik.x509.X509Certificate;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.activation.DataSource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.opensaml.saml2.core.StatusCode;
import org.xml.sax.SAXException;

import at.gv.egovernment.moa.id.auth.AuthenticationServer;
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.data.IdentityLink;
import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
import at.gv.egovernment.moa.id.auth.exception.BKUException;
import at.gv.egovernment.moa.id.auth.exception.BuildException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.auth.exception.ParseException;
import at.gv.egovernment.moa.id.auth.exception.ServiceException;
import at.gv.egovernment.moa.id.auth.stork.STORKException;
import at.gv.egovernment.moa.id.auth.stork.STORKResponseProcessor;
import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
import at.gv.egovernment.moa.id.commons.db.dao.config.AttributeProviderPlugin;
import at.gv.egovernment.moa.id.config.ConfigurationException;
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.protocols.pvp2x.PVPConstants;
import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
import at.gv.egovernment.moa.id.util.HTTPUtils;
import at.gv.egovernment.moa.id.util.VelocityProvider;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.spss.MOAException;
import at.gv.egovernment.moa.spss.api.SPSSFactory;
import at.gv.egovernment.moa.spss.api.SignatureVerificationService;
import at.gv.egovernment.moa.spss.api.common.Content;

import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureInfo;
import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureLocation;
import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest;
import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse;
import at.gv.egovernment.moa.util.StringUtils;
import at.gv.util.xsd.xmldsig.SignatureType;
import at.gv.util.xsd.xmldsig.X509DataType;
import eu.stork.oasisdss.api.ApiUtils;
import eu.stork.oasisdss.api.LightweightSourceResolver;
import eu.stork.oasisdss.api.exceptions.ApiUtilsException;
import eu.stork.oasisdss.api.exceptions.UtilsException;
import eu.stork.oasisdss.profile.SignRequest;
import eu.stork.oasisdss.profile.SignResponse;
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.STORKAuthnRequest;
import eu.stork.peps.auth.commons.STORKAuthnResponse;
import eu.stork.peps.auth.engine.STORKSAMLEngine;
import eu.stork.peps.exceptions.STORKSAMLEngineException;
//import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse;

/**
 * Endpoint for receiving STORK response messages
 * @deprecated Use {@link at.gv.egovernment.moa.id.auth.modules.stork.tasks.PepsConnectorHandleResponseWithoutSignatureTask} instead.
 */
public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {
    private static final long serialVersionUID = 1L;

    public static final String PEPSCONNECTOR_SERVLET_URL_PATTERN = "/PEPSConnectorWithLocalSigning";

    private String oasisDssWebFormURL = "https://testvidp.buergerkarte.at/oasis-dss/DSSWebFormServlet";//load from config below

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        super.doGet(request, response);
    }

    /**
     * Handles the reception of a STORK response message
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");

        String moaSessionID1 = request.getParameter("moaSessionID");
        String signResponse = request.getParameter("signresponse");
        Logger.info("moaSessionID1:" + moaSessionID1);
        Logger.info("signResponse:" + signResponse);
        if (moaSessionID1 != null) {
            if (signResponse != null) {
                //redirect from oasis with signresponse
                handleSignResponse(request, response);
            } else {
                //should not occur
                throw new IOException("should not occur");
            }
        } else {
            if (signResponse != null) {
                //should not occur
                throw new IOException("should not occur");
            } else {
                //normal saml response
                handleSAMLResponse(request, response);
            }
        }
        return;
    }

    private void handleSignResponse(HttpServletRequest request, HttpServletResponse response) {
        Logger.info("handleSignResponse started");
        String moaSessionID = request.getParameter("moaSessionID");
        String signResponse = request.getParameter("signresponse");
        Logger.info("moaSessionID:" + moaSessionID);
        Logger.info("signResponse:" + signResponse);
        String pendingRequestID = null;
        try {

            //load MOASession from database
            AuthenticationSession moaSession = AuthenticationServer.getSession(moaSessionID);
            //change MOASessionID
            moaSessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);

            pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moaSessionID);
            Logger.info("pendingRequestID:" + pendingRequestID);
            String signResponseString = new String(Base64.decodeBase64(signResponse), "UTF8");
            Logger.info("RECEIVED signresponse:" + signResponseString);
            //create SignResponse object
            Source response1 = new StreamSource(new java.io.StringReader(signResponseString));
            SignResponse dssSignResponse = ApiUtils.unmarshal(response1, SignResponse.class);

            //         SignResponse dssSignResponse = (SignResponse) ApiUtils.unmarshal(new StreamSource(new java.io.StringReader(Base64.signResponse)));

            String citizenSignature = getCitizienSignatureFromSignResponse(dssSignResponse);

            // memorize signature into authblock
            moaSession.setAuthBlock(citizenSignature);

            X509Certificate cert = getSignerCertificate(citizenSignature);
            moaSession.setSignerCertificate(cert);
            VerifyXMLSignatureResponse xMLVerifySignatureResponse = verifyXMLSignature(citizenSignature);
            at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse tmp = convert(xMLVerifySignatureResponse);

            moaSession.setXMLVerifySignatureResponse(tmp);
            try {
                IPersonalAttributeList personalAttributeList = moaSession
                        .getAuthnResponseGetPersonalAttributeList();
                //Add SignResponse   TODO Add signature (extracted from signResponse)?
                List<String> values = new ArrayList<String>();
                values.add(signResponseString);
                //            values.add(citizenSignature);
                Logger.debug("Assembling signedDoc attribute");
                PersonalAttribute signedDocAttribute = new PersonalAttribute("signedDoc", false, values,
                        "Available");
                personalAttributeList.add(signedDocAttribute);

                String authnContextClassRef = moaSession.getAuthnContextClassRef();
                SZRGInsertion(moaSession, personalAttributeList, authnContextClassRef, citizenSignature);
            } catch (STORKException e) {
                // this is really nasty but we work against the system here. We are supposed to get the gender attribute from
                // stork. If we do not, we cannot register the person in the ERnP - we have to have the
                // gender for the represented person. So here comes the dirty hack. 
                if (e.getCause() instanceof STORKException
                        && e.getCause().getMessage().equals("gender not found in response")) {
                    try {
                        Logger.trace("Initialize VelocityEngine...");

                        VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
                        Template template = velocityEngine.getTemplate("/resources/templates/fetchGender.html");
                        VelocityContext context = new VelocityContext();
                        context.put("SAMLResponse", request.getParameter("SAMLResponse"));
                        context.put("action", request.getRequestURL());

                        StringWriter writer = new StringWriter();
                        template.merge(context, writer);

                        response.getOutputStream().write(writer.toString().getBytes("UTF-8"));
                    } catch (Exception e1) {
                        Logger.error("Error sending gender retrival form.", e1);
                        //                  httpSession.invalidate();
                        throw new MOAIDException("stork.10", null);
                    }

                    return;
                }

                Logger.error("Error connecting SZR Gateway", e);
                throw new MOAIDException("stork.10", null);
            }

            Logger.debug("Add full STORK AuthnResponse to MOA session");
            moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));//TODO ask Florian/Thomas authnResponse?
            moaSession.setForeigner(true);

            //session is implicit stored in changeSessionID!!!!
            String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);

            Logger.info("Changed MOASession " + moaSessionID + " to Session " + newMOASessionID);

            //redirect
            String redirectURL = null;
            redirectURL = new DataURLBuilder().buildDataURL(moaSession.getAuthURL(),
                    ModulUtils.buildAuthURL(moaSession.getModul(), moaSession.getAction(), pendingRequestID),
                    newMOASessionID);
            redirectURL = response.encodeRedirectURL(redirectURL);

            response.sendRedirect(redirectURL);
            Logger.info("REDIRECT TO: " + redirectURL);

        } catch (AuthenticationException e) {
            handleError(null, e, request, response, pendingRequestID);

        } catch (MOAIDException e) {
            handleError(null, e, request, response, pendingRequestID);

        } catch (Exception e) {
            Logger.error("PEPSConnector has an interal Error.", e);
        }

        finally {
            ConfigurationDBUtils.closeSession();
        }
    }

    private void handleSAMLResponse(HttpServletRequest request, HttpServletResponse response) {
        Logger.info("handleSAMLResponse started");
        String pendingRequestID = null;

        try {
            Logger.info("PEPSConnector Servlet invoked, expecting C-PEPS message.");
            Logger.debug("This ACS endpoint is: " + HTTPUtils.getBaseURL(request));

            super.setNoCachingHeadersInHttpRespone(request, response);
            Logger.trace("No Caching headers set for HTTP response");

            //check if https or only http
            super.checkIfHTTPisAllowed(request.getRequestURL().toString());

            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(request.getParameter("SAMLResponse"));
                Logger.debug("SAMLResponse: " + new String(decSamlToken));

            } catch (NullPointerException e) {
                Logger.error("Unable to retrieve STORK Response", e);
                throw new MOAIDException("stork.04", null);
            }

            //Get SAMLEngine instance
            STORKSAMLEngine engine = STORKSAMLEngine.getInstance("outgoing");

            STORKAuthnResponse authnResponse = null;
            try {
                //validate SAML Token
                Logger.debug("Starting validation of SAML response");
                authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, (String) request.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);
            }

            Logger.info("STORK SAML Response message succesfully extracted");
            Logger.debug("STORK response: ");
            Logger.debug(authnResponse.toString());

            Logger.debug("Trying to find MOA Session-ID ...");
            //String moaSessionID = request.getParameter(PARAM_SESSIONID);
            //first use SAML2 relayState 
            String moaSessionID = request.getParameter("RelayState");

            // escape parameter strings
            moaSessionID = StringEscapeUtils.escapeHtml(moaSessionID);

            //check if SAML2 relaystate includes a MOA sessionID
            if (StringUtils.isEmpty(moaSessionID)) {
                //if relaystate is emtpty, use SAML response -> inResponseTo element as session identifier

                moaSessionID = authnResponse.getInResponseTo();
                moaSessionID = StringEscapeUtils.escapeHtml(moaSessionID);

                if (StringUtils.isEmpty(moaSessionID)) {
                    //No authentication session has been started before
                    Logger.error("MOA-SessionID was not found, no previous AuthnRequest had been started");
                    Logger.debug("PEPSConnectorURL was: " + request.getRequestURL());
                    throw new AuthenticationException("auth.02", new Object[] { moaSessionID });

                } else
                    Logger.trace(
                            "Use MOA SessionID " + moaSessionID + " from AuthnResponse->inResponseTo attribute.");

            } else
                //Logger.trace("MOA SessionID " + moaSessionID + " is found in http GET parameter.");
                Logger.trace("MOA SessionID " + moaSessionID + " is found in SAML2 relayState.");

            /*INFO!!!!
             * SAML message IDs has an different format then MOASessionIDs
             * This is only a workaround because many PEPS does not support SAML2 relayState or
             * MOASessionID as AttributConsumerServiceURL GET parameter
             */
            //            if (!ParamValidatorUtils.isValidSessionID(moaSessionID))
            //                throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID, "auth.12");

            pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moaSessionID);

            //load MOASession from database
            AuthenticationSession moaSession = AuthenticationServer.getSession(moaSessionID);
            //change MOASessionID
            moaSessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);

            Logger.info("Found MOA sessionID: " + moaSessionID);

            String statusCodeValue = authnResponse.getStatusCode();

            if (!statusCodeValue.equals(StatusCode.SUCCESS_URI)) {
                Logger.error("Received ErrorResponse from PEPS: " + statusCodeValue);
                throw new MOAIDException("stork.06", new Object[] { statusCodeValue });
            }

            Logger.info("Got SAML response with authentication success message.");

            Logger.debug("MOA session is still valid");

            STORKAuthnRequest storkAuthnRequest = moaSession.getStorkAuthnRequest();

            if (storkAuthnRequest == null) {
                Logger.error(
                        "Could not find any preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
                throw new MOAIDException("stork.07", null);
            }

            Logger.debug("Found a preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);

            ////////////// incorporate gender from parameters if not in stork response

            IPersonalAttributeList attributeList = authnResponse.getPersonalAttributeList();

            // but first, check if we have a representation case
            if (STORKResponseProcessor.hasAttribute("mandateContent", attributeList)
                    || STORKResponseProcessor.hasAttribute("representative", attributeList)
                    || STORKResponseProcessor.hasAttribute("represented", attributeList)) {
                // in a representation case...
                moaSession.setUseMandate("true");

                // and check if we have the gender value
                PersonalAttribute gender = attributeList.get("gender");
                if (null == gender) {
                    String gendervalue = (String) request.getParameter("gender");
                    if (null != gendervalue) {
                        gender = new PersonalAttribute();
                        gender.setName("gender");
                        ArrayList<String> tmp = new ArrayList<String>();
                        tmp.add(gendervalue);
                        gender.setValue(tmp);

                        authnResponse.getPersonalAttributeList().add(gender);
                    }
                }
            }

            //////////////////////////////////////////////////////////////////////////

            Logger.debug("Starting extraction of signedDoc attribute");
            //extract signed doc element and citizen signature
            String citizenSignature = null;
            try {
                PersonalAttribute signedDoc = authnResponse.getPersonalAttributeList().get("signedDoc");
                String signatureInfo = null;
                if (signedDoc != null) {
                    signatureInfo = signedDoc.getValue().get(0);
                    //should not occur
                } else {

                    //store SAMLResponse
                    moaSession.setSAMLResponse(request.getParameter("SAMLResponse"));
                    //store authnResponse

                    //moaSession.setAuthnResponse(authnResponse);//not serializable
                    moaSession.setAuthnResponseGetPersonalAttributeList(authnResponse.getPersonalAttributeList());

                    String authnContextClassRef = null;
                    try {
                        authnContextClassRef = authnResponse.getAssertions().get(0).getAuthnStatements().get(0)
                                .getAuthnContext().getAuthnContextClassRef().getAuthnContextClassRef();
                    } catch (Throwable e) {
                        Logger.warn(
                                "STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level");
                    }

                    moaSession.setAuthnContextClassRef(authnContextClassRef);
                    moaSession.setReturnURL(request.getRequestURL());

                    //load signedDoc
                    String signRequest = moaSession.getSignedDoc();

                    //session is implicit stored in changeSessionID!!!!
                    String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);

                    //set return url to PEPSConnectorWithLocalSigningServlet and add newMOASessionID 
                    //signRequest

                    String issuerValue = AuthConfigurationProvider.getInstance().getPublicURLPrefix();
                    String acsURL = issuerValue
                            + PEPSConnectorWithLocalSigningServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN;

                    String url = acsURL + "?moaSessionID=" + newMOASessionID;
                    //redirect to OASIS module and sign there

                    boolean found = false;
                    try {
                        List<AttributeProviderPlugin> aps = AuthConfigurationProvider.getInstance()
                                .getOnlineApplicationParameter(moaSession.getPublicOAURLPrefix()).getStorkAPs();
                        Logger.info("Found AttributeProviderPlugins:" + aps.size());
                        for (AttributeProviderPlugin ap : aps) {
                            Logger.info("Found AttributeProviderPlugin attribute:" + ap.getAttributes());
                            if (ap.getAttributes().equalsIgnoreCase("signedDoc")) {
                                // FIXME[tlenz]: A servlet's class field is not thread safe.
                                oasisDssWebFormURL = ap.getUrl();
                                found = true;
                                Logger.info("Loaded signedDoc attribute provider url from config:"
                                        + oasisDssWebFormURL);
                                break;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        Logger.error("Loading the signedDoc attribute provider url from config failed");
                    }
                    if (!found) {
                        Logger.error("Failed to load the signedDoc attribute provider url from config");
                    }
                    performRedirect(url, request, response, signRequest);

                    return;
                }
                SignResponse dssSignResponse = (SignResponse) ApiUtils
                        .unmarshal(new StreamSource(new java.io.StringReader(signatureInfo)));

                citizenSignature = getCitizienSignatureFromSignResponse(dssSignResponse);

                // memorize signature into authblock
                moaSession.setAuthBlock(citizenSignature);

                X509Certificate cert = getSignerCertificate(citizenSignature);
                moaSession.setSignerCertificate(cert);
                moaSession.setForeigner(true);

            } catch (Throwable e) {
                Logger.error("Could not extract citizen signature from C-PEPS", e);
                throw new MOAIDException("stork.09", null);
            }

            try {
                SZRGInsertion(moaSession, authnResponse.getPersonalAttributeList(),
                        authnResponse.getAssertions().get(0).getAuthnStatements().get(0).getAuthnContext()
                                .getAuthnContextClassRef().getAuthnContextClassRef(),
                        citizenSignature);
            } catch (STORKException e) {
                // this is really nasty but we work against the system here. We are supposed to get the gender attribute from
                // stork. If we do not, we cannot register the person in the ERnP - we have to have the
                // gender for the represented person. So here comes the dirty hack. 
                if (e.getCause() instanceof STORKException
                        && e.getCause().getMessage().equals("gender not found in response")) {
                    try {
                        Logger.trace("Initialize VelocityEngine...");

                        VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
                        Template template = velocityEngine.getTemplate("/resources/templates/fetchGender.html");
                        VelocityContext context = new VelocityContext();
                        context.put("SAMLResponse", request.getParameter("SAMLResponse"));
                        context.put("action", request.getRequestURL());

                        StringWriter writer = new StringWriter();
                        template.merge(context, writer);

                        response.getOutputStream().write(writer.toString().getBytes("UTF-8"));
                    } catch (Exception e1) {
                        Logger.error("Error sending gender retrival form.", e1);
                        //                  httpSession.invalidate();
                        throw new MOAIDException("stork.10", null);
                    }

                    return;
                }

                Logger.error("Error connecting SZR Gateway", e);
                throw new MOAIDException("stork.10", null);
            }

            Logger.debug("Add full STORK AuthnResponse to MOA session");
            moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));//TODO ask Florian/Thomas authnResponse?

            //session is implicit stored in changeSessionID!!!!
            String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);

            Logger.info("Changed MOASession " + moaSessionID + " to Session " + newMOASessionID);

            //redirect
            String redirectURL = null;
            redirectURL = new DataURLBuilder().buildDataURL(moaSession.getAuthURL(),
                    ModulUtils.buildAuthURL(moaSession.getModul(), moaSession.getAction(), pendingRequestID),
                    newMOASessionID);
            redirectURL = response.encodeRedirectURL(redirectURL);

            response.setContentType("text/html");
            response.setStatus(302);
            response.addHeader("Location", redirectURL);
            Logger.info("REDIRECT TO: " + redirectURL);

        } catch (AuthenticationException e) {
            handleError(null, e, request, response, pendingRequestID);

        } catch (MOAIDException e) {
            handleError(null, e, request, response, pendingRequestID);

        } catch (Exception e) {
            Logger.error("PEPSConnector has an interal Error.", e);
        }

        finally {
            ConfigurationDBUtils.closeSession();
        }

    }

    private void performRedirect(String url, HttpServletRequest req, HttpServletResponse resp,
            String signRequestString) throws MOAIDException {

        try {
            Logger.trace("Initialize VelocityEngine...");

            VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
            Template template = velocityEngine.getTemplate("/resources/templates/oasis_dss_webform_binding.vm");
            VelocityContext context = new VelocityContext();

            Logger.debug("performRedirect, signrequest:" + signRequestString);
            Source signDoc = new StreamSource(new java.io.StringReader(signRequestString));
            SignRequest signRequest = ApiUtils.unmarshal(signDoc, SignRequest.class);
            signRequest.setReturnURL("TODO");
            signRequestString = IOUtils.toString(ApiUtils.marshalToInputStream(signRequest));
            context.put("signrequest", Base64.encodeBase64String(signRequestString.getBytes("UTF8")));
            context.put("clienturl", url);
            context.put("action", oasisDssWebFormURL);

            StringWriter writer = new StringWriter();
            template.merge(context, writer);

            resp.getOutputStream().write(writer.toString().getBytes("UTF-8"));
        } catch (Exception e) {
            Logger.error("Error sending DSS signrequest.", e);
            throw new MOAIDException("stork.11", null);
        }
    }

    private String getCitizienSignatureFromSignResponseFromSAML(STORKAuthnResponse authnResponse)
            throws ApiUtilsException, IllegalArgumentException, TransformerConfigurationException, UtilsException,
            TransformerException, TransformerFactoryConfigurationError, IOException, MOAIDException {
        PersonalAttribute signedDoc = authnResponse.getPersonalAttributeList().get("signedDoc");
        String signatureInfo = null;
        if (signedDoc == null) {
            Logger.error("SignedDoc = null, failed to extract Signresponse from authnResponse");
            throw new MOAIDException("stork.09", null);
        }
        signatureInfo = signedDoc.getValue().get(0);

        SignResponse dssSignResponse = (SignResponse) ApiUtils
                .unmarshal(new StreamSource(new java.io.StringReader(signatureInfo)));
        String citizenSignature = getCitizienSignatureFromSignResponse(dssSignResponse);
        return citizenSignature;

    }

    private String getCitizienSignatureFromSignResponse(SignResponse dssSignResponse)
            throws IllegalArgumentException, TransformerConfigurationException, UtilsException,
            TransformerException, TransformerFactoryConfigurationError, IOException, ApiUtilsException {
        // fetch signed doc
        DataSource ds = LightweightSourceResolver.getDataSource(dssSignResponse);
        if (ds == null) {
            throw new ApiUtilsException("No datasource found in response");
        }

        InputStream incoming = ds.getInputStream();
        String citizenSignature = IOUtils.toString(incoming);
        incoming.close();

        return citizenSignature;
    }

    private X509Certificate getSignerCertificate(String citizenSignature)
            throws CertificateException, JAXBException, UnsupportedEncodingException {
        JAXBContext ctx = JAXBContext.newInstance(SignatureType.class.getPackage().getName());
        SignatureType root = ((JAXBElement<SignatureType>) ctx.createUnmarshaller()
                .unmarshal(IOUtils.toInputStream(citizenSignature))).getValue();

        // extract certificate
        for (Object current : root.getKeyInfo().getContent())
            if (((JAXBElement<?>) current).getValue() instanceof X509DataType) {
                for (Object currentX509Data : ((JAXBElement<X509DataType>) current).getValue()
                        .getX509IssuerSerialOrX509SKIOrX509SubjectName()) {
                    JAXBElement<?> casted = ((JAXBElement<?>) currentX509Data);
                    if (casted.getName().getLocalPart().equals("X509Certificate")) {
                        return new X509Certificate(((String) casted.getValue()).getBytes("UTF-8"));
                    }
                }
            }
        return null;
    }

    private void SZRGInsertion(AuthenticationSession moaSession, IPersonalAttributeList personalAttributeList,
            String authnContextClassRef, String citizenSignature) throws STORKException, MOAIDException {
        Logger.debug("Foregin Citizen signature successfully extracted from STORK Assertion (signedDoc)");
        Logger.debug("Citizen signature will be verified by SZR Gateway!");

        Logger.debug("fetching OAParameters from database");

        OAAuthParameter oaParam = AuthConfigurationProvider.getInstance()
                .getOnlineApplicationParameter(moaSession.getPublicOAURLPrefix());
        if (oaParam == null)
            throw new AuthenticationException("auth.00", new Object[] { moaSession.getPublicOAURLPrefix() });

        // retrieve target
        //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_ + moaSession.getDomainIdentifier();
        } else {
            targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
        }

        Logger.debug("Starting connecting SZR Gateway");
        //contact SZR Gateway
        IdentityLink identityLink = null;

        identityLink = STORKResponseProcessor.connectToSZRGateway(personalAttributeList, oaParam.getFriendlyName(),
                targetType, null, oaParam.getMandateProfiles(), citizenSignature);
        Logger.debug("SZR communication was successfull");

        if (identityLink == null) {
            Logger.error("SZR Gateway did not return an identity link.");
            throw new MOAIDException("stork.10", null);
        }
        Logger.info("Received Identity Link from SZR Gateway");
        moaSession.setIdentityLink(identityLink);

        Logger.debug("Adding addtional STORK attributes to MOA session");
        moaSession.setStorkAttributes(personalAttributeList);

        //We don't have BKUURL, setting from null to "Not applicable"
        moaSession.setBkuURL("Not applicable (STORK Authentication)");

        // free for single use
        moaSession.setAuthenticatedUsed(false);

        // stork did the authentication step
        moaSession.setAuthenticated(true);

        //TODO: found better solution, but QAA Level in response could be not supported yet
        try {
            if (authnContextClassRef == null)
                authnContextClassRef = PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel();
            moaSession.setQAALevel(authnContextClassRef);

        } catch (Throwable e) {
            Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level");
            moaSession.setQAALevel(PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel());

        }

    }

    private VerifyXMLSignatureResponse verifyXMLSignature(String signature) throws AuthenticationException,
            ParseException, BKUException, BuildException, ConfigurationException, ServiceException,
            UnsupportedEncodingException, SAXException, IOException, ParserConfigurationException, MOAException {
        //Based on MOA demo client
        // Factory und Service instanzieren
        SPSSFactory spssFac = SPSSFactory.getInstance();
        SignatureVerificationService sigVerifyService = SignatureVerificationService.getInstance();

        Content sigDocContent1 = spssFac.createContent(IOUtils.toInputStream(signature, "UTF-8"), null);

        // Position der zu prfenden Signatur im Dokument angeben
        // (Nachdem im XPath-Ausdruck ein NS-Prfix verwendet wird, muss in einer Lookup-Tabelle
        // der damit bezeichnete Namenraum mitgegeben werden)
        HashMap nSMap = new HashMap();
        nSMap.put("dsig", "http://www.w3.org/2000/09/xmldsig#");
        VerifySignatureLocation sigLocation = spssFac.createVerifySignatureLocation("//dsig:Signature", nSMap);

        // Zu prfendes Dokument und Signaturposition zusammenfassen

        VerifySignatureInfo sigInfo = spssFac.createVerifySignatureInfo(sigDocContent1, sigLocation);

        // Prfrequest zusammenstellen
        VerifyXMLSignatureRequest verifyRequest = spssFac.createVerifyXMLSignatureRequest(null, // Wird Prfzeit nicht angegeben, wird aktuelle Zeit verwendet 
                sigInfo, null, // Keine Ergnzungsobjekte notwendig
                null, // Signaturmanifest-Prfung soll nicht durchgefhrt werden
                false, // Hash-Inputdaten, d.h. tatschlich signierte Daten werden nicht zurckgeliefert
                "MOAIDBuergerkartePersonenbindungMitTestkarten");//TODO load from config
        //"Test-Signaturdienste");  // ID des verwendeten Vertrauensprofils

        VerifyXMLSignatureResponse verifyResponse = null;
        try {
            // Aufruf der Signaturprfung
            verifyResponse = sigVerifyService.verifyXMLSignature(verifyRequest);
        } catch (MOAException e) {
            // Service liefert Fehler
            System.err.println("Die Signaturprfung hat folgenden Fehler geliefert:");
            System.err.println("Fehlercode: " + e.getMessageId());
            System.err.println("Fehlernachricht: " + e.getMessage());
            throw e;
        }

        //          // Auswertung der Response
        //          System.out.println();
        //          System.out.println("Ergebnisse der Signaturprfung:");
        //          System.out.println();
        //          
        //          // Besondere Eigenschaften des Signatorzertifikats
        //          SignerInfo signerInfo = verifyResponse.getSignerInfo();
        //          System.out.println("*** Ist Zertifikat des Signators qualifiziert? " + ((signerInfo.isQualifiedCertificate()) ? "ja" : "nein"));
        //          System.out.println("*** Ist Zertifikat des Signators von einer Behrde? " + ((signerInfo.isPublicAuthority()) ? "ja" : "nein"));
        //          
        //          // Ergebnisse von Signatur- und Zertifikatsprfung
        //          System.out.println();
        //          System.out.println("Ergebniscode der Signaturprfung: " + verifyResponse.getSignatureCheck().getCode());
        //          System.out.println("Ergebniscode der Zertifikatsprfung: " + verifyResponse.getCertificateCheck().getCode());
        //          
        //          // Signatorzertifikat
        //          System.out.println();
        //          System.out.println("*** Zertifikat des Signators:");
        //          System.out.println("Aussteller: " + signerInfo.getSignerCertificate().getIssuerDN());
        //          System.out.println("Subject: " + signerInfo.getSignerCertificate().getSubjectDN());
        //          System.out.println("Seriennummer: " + signerInfo.getSignerCertificate().getSerialNumber());
        return verifyResponse;
    }

    private at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse convert(
            VerifyXMLSignatureResponse xMLVerifySignatureResponse) {
        at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse response = new at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse();
        response.setCertificateCheckCode(xMLVerifySignatureResponse.getCertificateCheck().getCode());
        response.setPublicAuthority(xMLVerifySignatureResponse.getSignerInfo().isPublicAuthority());
        //      response.setPublicAuthorityCode(publicAuthorityCode)
        response.setQualifiedCertificate(xMLVerifySignatureResponse.getSignerInfo().isQualifiedCertificate());
        response.setSignatureCheckCode(xMLVerifySignatureResponse.getSignatureCheck().getCode());
        response.setSignatureManifestCheckCode(xMLVerifySignatureResponse.getSignatureManifestCheck().getCode());
        //      response.setSigningDateTime()
        //      response.setX509certificate(x509certificate)
        response.setXmlDSIGManifestCheckCode(xMLVerifySignatureResponse.getSignatureManifestCheck().getCode());
        //      response.setXmlDSIGManigest(xMLVerifySignatureResponse.getSignatureManifestCheck())
        //      response.setXmlDsigSubjectName(xmlDsigSubjectName)   
        return response;
    }
}