at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol.java Source code

Java tutorial

Introduction

Here is the source code for at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol.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.protocols.pvp2x;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.TransformerException;

import org.apache.commons.lang.StringEscapeUtils;
import org.joda.time.DateTime;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.core.AttributeQuery;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.LogoutRequest;
import org.opensaml.saml2.core.LogoutResponse;
import org.opensaml.saml2.core.NameID;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.Status;
import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.core.StatusMessage;
import org.opensaml.saml2.core.impl.AuthnRequestImpl;
import org.opensaml.saml2.metadata.AssertionConsumerService;
import org.opensaml.saml2.metadata.AttributeConsumingService;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.ws.security.SecurityPolicyException;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.security.SecurityException;
import org.opensaml.xml.signature.SignableXMLObject;

import java.util.Arrays;

import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.auth.exception.ProtocolNotActiveException;
import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
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.IAction;
import at.gv.egovernment.moa.id.moduls.IModulInfo;
import at.gv.egovernment.moa.id.moduls.IRequest;
import at.gv.egovernment.moa.id.moduls.NoPassivAuthenticationException;
import at.gv.egovernment.moa.id.moduls.RequestImpl;
import at.gv.egovernment.moa.id.moduls.RequestStorage;
import at.gv.egovernment.moa.id.moduls.SSOManager;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IDecoder;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.SoapBinding;
import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage;
import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;
import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding;
import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionValidationExeption;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AttributQueryException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.InvalidAssertionConsumerServiceException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.MandateAttributesNotHandleAbleException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NameIDFormatNotSupportedException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SLOException;
import at.gv.egovernment.moa.id.protocols.pvp2x.utils.CheckMandateAttributes;
import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
import at.gv.egovernment.moa.id.protocols.pvp2x.validation.AuthnRequestValidator;
import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngine;
import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory;
import at.gv.egovernment.moa.id.util.ErrorResponseUtils;
import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
import at.gv.egovernment.moa.id.util.VelocityLogAdapter;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;

public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {

    public static final String NAME = PVP2XProtocol.class.getName();
    public static final String PATH = "id_pvp2x";

    public static final String REDIRECT = "Redirect";
    public static final String POST = "Post";
    public static final String SOAP = "Soap";
    public static final String METADATA = "Metadata";
    public static final String ATTRIBUTEQUERY = "AttributeQuery";
    public static final String SINGLELOGOUT = "SingleLogOut";

    public static final String ENDPOINT_IDP = "idp";
    public static final String ENDPOINT_SP = "sp";

    public static final String PARAMETER_ENDPOINT = "endpointtype";

    private static List<IDecoder> decoder = new ArrayList<IDecoder>();

    private static HashMap<String, IAction> actions = new HashMap<String, IAction>();

    public static final List<String> DEFAULTREQUESTEDATTRFORINTERFEDERATION = Arrays
            .asList(new String[] { PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME });

    static {
        decoder.add(new PostBinding());
        decoder.add(new RedirectBinding());
        decoder.add(new SoapBinding());

        actions.put(REDIRECT, new AuthenticationAction());
        actions.put(POST, new AuthenticationAction());
        actions.put(METADATA, new MetadataAction());
        actions.put(ATTRIBUTEQUERY, new AttributQueryAction());
        actions.put(SINGLELOGOUT, new SingleLogOutAction());

        //TODO: insert getArtifact action

        instance = new PVP2XProtocol();

        new VelocityLogAdapter();
    }

    private static PVP2XProtocol instance = null;

    public static PVP2XProtocol getInstance() {
        if (instance == null) {
            instance = new PVP2XProtocol();
        }
        return instance;
    }

    public String getName() {
        return NAME;
    }

    public String getPath() {
        return PATH;
    }

    private IDecoder findDecoder(String action, HttpServletRequest req) {
        Iterator<IDecoder> decoderIT = decoder.iterator();
        while (decoderIT.hasNext()) {
            IDecoder decoder = decoderIT.next();
            if (decoder.handleDecode(action, req)) {
                return decoder;
            }
        }

        return null;
    }

    private boolean isServiceProviderEndPointUsed(HttpServletRequest req) throws InvalidProtocolRequestException {
        Object obj = req.getParameter(PARAMETER_ENDPOINT);
        if (obj instanceof String) {
            String param = (String) obj;
            if (MiscUtil.isNotEmpty(param)) {
                if (ENDPOINT_IDP.equals(param))
                    return false;

                else if (ENDPOINT_SP.equals(param))
                    return true;
            }
        }

        Logger.error("No valid PVP 2.1 entpoint descriptor");
        throw new InvalidProtocolRequestException("pvp2.20", new Object[] {});
    }

    public PVP2XProtocol() {
        super();
    }

    public IRequest preProcess(HttpServletRequest request, HttpServletResponse response, String action)
            throws MOAIDException {

        if (!AuthConfigurationProvider.getInstance().getAllowedProtocols().isPVP21Active()) {
            Logger.info("PVP2.1 is deaktivated!");
            throw new ProtocolNotActiveException("auth.22", new java.lang.Object[] { NAME });

        }

        if (METADATA.equals(action)) {
            return new PVPTargetConfiguration();

        }

        IDecoder decoder = findDecoder(action, request);
        if (decoder == null) {
            return null;
        }
        try {

            InboundMessage msg = (InboundMessage) decoder.decode(request, response,
                    isServiceProviderEndPointUsed(request));

            if (MiscUtil.isEmpty(msg.getEntityID())) {
                throw new InvalidProtocolRequestException("pvp2.20", new Object[] {});

            }

            if (!msg.isVerified()) {
                SAMLVerificationEngine engine = new SAMLVerificationEngine();
                engine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine());
                msg.setVerified(true);

            }

            if (msg instanceof MOARequest && ((MOARequest) msg).getSamlRequest() instanceof AuthnRequest)
                return preProcessAuthRequest(request, response, (MOARequest) msg);

            else if (msg instanceof MOARequest && ((MOARequest) msg).getSamlRequest() instanceof AttributeQuery)
                return preProcessAttributQueryRequest(request, response, (MOARequest) msg);

            else if (msg instanceof MOARequest && ((MOARequest) msg).getSamlRequest() instanceof LogoutRequest)
                return preProcessLogOut(request, response, msg);

            else if (msg instanceof MOAResponse && ((MOAResponse) msg).getResponse() instanceof LogoutResponse)
                return preProcessLogOut(request, response, msg);

            else if (msg instanceof MOAResponse && ((MOAResponse) msg).getResponse() instanceof Response) {
                //load service provider AuthRequest from session

                IRequest obj = RequestStorage.getPendingRequest(msg.getRelayState());
                if (obj instanceof RequestImpl) {
                    RequestImpl iReqSP = (RequestImpl) obj;

                    MOAResponse processedMsg = preProcessAuthResponse((MOAResponse) msg);

                    if (processedMsg != null) {
                        iReqSP.setInterfederationResponse(processedMsg);

                    } else {
                        Logger.info("Interfederated IDP " + msg.getEntityID() + " has NO valid SSO session."
                                + ". Switch back local authentication process ...");

                        SSOManager ssomanager = SSOManager.getInstance();
                        ssomanager.removeInterfederatedSSOIDP(msg.getEntityID(), request);

                        iReqSP.setRequestedIDP(null);

                    }

                    return iReqSP;

                }

                Logger.error("Stored PVP21 authrequest from service provider has an unsuppored type.");
                return null;

            } else {
                Logger.error("Receive unsupported PVP21 message");
                throw new MOAIDException("Unsupported PVP21 message", new Object[] {});
            }

        } catch (PVP2Exception e) {
            throw e;

        } catch (SecurityPolicyException e) {
            String samlRequest = request.getParameter("SAMLRequest");
            Logger.warn("Receive INVALID protocol request: " + samlRequest, e);
            throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});

        } catch (SecurityException e) {
            String samlRequest = request.getParameter("SAMLRequest");
            Logger.warn("Receive INVALID protocol request: " + samlRequest, e);
            throw new InvalidProtocolRequestException("pvp2.22", new Object[] { e.getMessage() });

        } catch (InvalidProtocolRequestException e) {
            String samlRequest = request.getParameter("SAMLRequest");
            Logger.warn("Receive INVALID protocol request: " + samlRequest, e);
            throw e;

        } catch (Throwable e) {
            String samlRequest = request.getParameter("SAMLRequest");
            Logger.warn("Receive INVALID protocol request: " + samlRequest, e);

            throw new MOAIDException(e.getMessage(), new Object[] {});
        }
    }

    public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response,
            IRequest protocolRequest) throws Throwable {

        if (protocolRequest == null) {
            throw e;
        }

        if (!(protocolRequest instanceof PVPTargetConfiguration)) {
            throw e;
        }
        PVPTargetConfiguration pvpRequest = (PVPTargetConfiguration) protocolRequest;

        Response samlResponse = SAML2Utils.createSAMLObject(Response.class);
        Status status = SAML2Utils.createSAMLObject(Status.class);
        StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class);
        StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class);

        ErrorResponseUtils errorUtils = ErrorResponseUtils.getInstance();
        String moaError = null;

        if (e instanceof NoPassivAuthenticationException) {
            statusCode.setValue(StatusCode.NO_PASSIVE_URI);
            statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));

        } else if (e instanceof NameIDFormatNotSupportedException) {
            statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY_URI);
            statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));

        } else if (e instanceof SLOException) {
            //SLOExecpetions only occurs if session information is lost
            return false;

        } else if (e instanceof PVP2Exception) {
            PVP2Exception ex = (PVP2Exception) e;
            statusCode.setValue(ex.getStatusCodeValue());
            String statusMessageValue = ex.getStatusMessageValue();
            if (statusMessageValue != null) {
                statusMessage.setMessage(StringEscapeUtils.escapeXml(statusMessageValue));
            }
            moaError = errorUtils.mapInternalErrorToExternalError(ex.getMessageId());

        } else {
            statusCode.setValue(StatusCode.RESPONDER_URI);
            statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
            moaError = errorUtils.getResponseErrorCode(e);
        }

        if (MiscUtil.isNotEmpty(moaError)) {
            StatusCode moaStatusCode = SAML2Utils.createSAMLObject(StatusCode.class);
            moaStatusCode.setValue(moaError);
            statusCode.setStatusCode(moaStatusCode);
        }

        status.setStatusCode(statusCode);
        if (statusMessage.getMessage() != null) {
            status.setStatusMessage(statusMessage);
        }
        samlResponse.setStatus(status);
        String remoteSessionID = SAML2Utils.getSecureIdentifier();
        samlResponse.setID(remoteSessionID);

        samlResponse.setIssueInstant(new DateTime());
        Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class);
        nissuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());
        nissuer.setFormat(NameID.ENTITY);
        samlResponse.setIssuer(nissuer);

        IEncoder encoder = null;

        if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
            encoder = new RedirectBinding();

        } else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_ARTIFACT_BINDING_URI)) {
            // TODO: not supported YET!!
            //binding = new ArtifactBinding();

        } else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) {
            encoder = new PostBinding();

        } else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) {
            encoder = new SoapBinding();
        }

        if (encoder == null) {
            // default to redirect binding
            encoder = new RedirectBinding();
        }

        String relayState = null;
        if (pvpRequest.getRequest() != null)
            relayState = pvpRequest.getRequest().getRelayState();

        encoder.encodeRespone(request, response, samlResponse, pvpRequest.getConsumerURL(), relayState);
        return true;
    }

    public IAction getAction(String action) {
        return actions.get(action);
    }

    public IAction canHandleRequest(HttpServletRequest request, HttpServletResponse response) {
        if (request.getParameter("SAMLRequest") != null && request.getMethod().equals("GET")) {
            return getAction(REDIRECT);

        } else if (request.getParameter("SAMLRequest") != null && request.getMethod().equals("POST")) {
            return getAction(POST);

        }

        if (METADATA.equals(request.getParameter("action"))) {
            return getAction(METADATA);
        }
        return null;
    }

    public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) {

        return true;
    }

    /**
     * PreProcess Single LogOut request
     * @param request
     * @param response
     * @param msg
     * @return
     * @throws MOAIDException 
     */
    private IRequest preProcessLogOut(HttpServletRequest request, HttpServletResponse response,
            InboundMessage inMsg) throws MOAIDException {

        PVPTargetConfiguration config = new PVPTargetConfiguration();

        MOARequest msg;
        if (inMsg instanceof MOARequest && ((MOARequest) inMsg).getSamlRequest() instanceof LogoutRequest) {
            //preProcess single logout request from service provider

            msg = (MOARequest) inMsg;

            EntityDescriptor metadata = msg.getEntityMetadata();
            if (metadata == null) {
                throw new NoMetadataInformationException();
            }

            String oaURL = metadata.getEntityID();
            oaURL = StringEscapeUtils.escapeHtml(oaURL);

            Logger.info("Dispatch PVP2 SingleLogOut: OAURL=" + oaURL + " Binding=" + msg.getRequestBinding());

            config.setOAURL(oaURL);
            config.setBinding(msg.getRequestBinding());

        } else if (inMsg instanceof MOAResponse && ((MOAResponse) inMsg).getResponse() instanceof LogoutResponse) {
            //preProcess single logour response from service provider

            LogoutResponse resp = (LogoutResponse) (((MOAResponse) inMsg).getResponse());

            Logger.debug("PreProcess SLO Response from " + resp.getIssuer());

            if (!resp.getDestination().startsWith(PVPConfiguration.getInstance().getIDPPublicPath())) {
                Logger.warn("PVP 2.1 single logout response destination does not match to IDP URL");
                throw new AssertionValidationExeption(
                        "PVP 2.1 single logout response destination does not match to IDP URL", null);

            }

            //TODO: check if relayState exists
            inMsg.getRelayState();

        } else
            throw new MOAIDException("Unsupported request", new Object[] {});

        config.setRequest(inMsg);
        config.setAction(SINGLELOGOUT);
        return config;
    }

    /**
     * PreProcess AttributeQuery request 
     * @param request
     * @param response
     * @param moaRequest
     * @return
     * @throws Throwable
     */
    private IRequest preProcessAttributQueryRequest(HttpServletRequest request, HttpServletResponse response,
            MOARequest moaRequest) throws Throwable {

        AttributeQuery attrQuery = (AttributeQuery) moaRequest.getSamlRequest();
        moaRequest.setEntityID(attrQuery.getIssuer().getValue());

        //validate destination
        String destinaten = attrQuery.getDestination();
        if (!PVPConfiguration.getInstance().getIDPAttributeQueryService().equals(destinaten)) {
            Logger.warn("AttributeQuery destination does not match IDP AttributeQueryService URL");
            throw new AttributQueryException(
                    "AttributeQuery destination does not match IDP AttributeQueryService URL", null);

        }

        //check if Issuer is an interfederation IDP
        // check parameter
        if (!ParamValidatorUtils.isValidOA(moaRequest.getEntityID()))
            throw new WrongParametersException("StartAuthentication", PARAM_OA, "auth.12");

        OAAuthParameter oa = AuthConfigurationProvider.getInstance()
                .getOnlineApplicationParameter(moaRequest.getEntityID());
        if (!oa.isInderfederationIDP()) {
            Logger.warn("AttributeQuery requests are only allowed for interfederation IDPs.");
            throw new AttributQueryException("AttributeQuery requests are only allowed for interfederation IDPs.",
                    null);

        }

        if (!oa.isOutboundSSOInterfederationAllowed()) {
            Logger.warn("Interfederation IDP " + oa.getPublicURLPrefix()
                    + " does not allow outgoing SSO interfederation.");
            throw new AttributQueryException("Interfederation IDP does not allow outgoing SSO interfederation.",
                    null);

        }

        PVPTargetConfiguration config = new PVPTargetConfiguration();
        config.setRequest(moaRequest);
        config.setOAURL(moaRequest.getEntityID());
        config.setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI);

        return config;
    }

    /**
     * PreProcess Authn request
     * @param request
     * @param response
     * @param moaRequest
     * @return
     * @throws Throwable
     */
    private IRequest preProcessAuthRequest(HttpServletRequest request, HttpServletResponse response,
            MOARequest moaRequest) throws Throwable {

        SignableXMLObject samlReq = moaRequest.getSamlRequest();

        if (!(samlReq instanceof AuthnRequest)) {
            throw new MOAIDException("Unsupported request", new Object[] {});
        }

        EntityDescriptor metadata = moaRequest.getEntityMetadata();
        if (metadata == null) {
            throw new NoMetadataInformationException();
        }
        SPSSODescriptor spSSODescriptor = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS);

        AuthnRequest authnRequest = (AuthnRequest) samlReq;

        //parse AssertionConsumerService
        AssertionConsumerService consumerService = null;
        if (MiscUtil.isNotEmpty(authnRequest.getAssertionConsumerServiceURL())
                && MiscUtil.isNotEmpty(authnRequest.getProtocolBinding())) {
            //use AssertionConsumerServiceURL from request 
            consumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class);
            consumerService.setBinding(authnRequest.getProtocolBinding());
            consumerService.setLocation(authnRequest.getAssertionConsumerServiceURL());

        } else {
            //use AssertionConsumerServiceIndex and select consumerService from metadata
            Integer aIdx = authnRequest.getAssertionConsumerServiceIndex();
            int assertionidx = 0;

            if (aIdx != null) {
                assertionidx = aIdx.intValue();

            } else {
                assertionidx = SAML2Utils.getDefaultAssertionConsumerServiceIndex(spSSODescriptor);

            }
            consumerService = spSSODescriptor.getAssertionConsumerServices().get(assertionidx);

            if (consumerService == null) {
                throw new InvalidAssertionConsumerServiceException(aIdx);

            }
        }

        //select AttributeConsumingService from request
        AttributeConsumingService attributeConsumer = null;
        Integer aIdx = authnRequest.getAttributeConsumingServiceIndex();
        int attributeIdx = 0;

        if (aIdx != null) {
            attributeIdx = aIdx.intValue();
        }

        if (spSSODescriptor.getAttributeConsumingServices() != null
                && spSSODescriptor.getAttributeConsumingServices().size() > 0) {
            attributeConsumer = spSSODescriptor.getAttributeConsumingServices().get(attributeIdx);
        }

        //validate AuthnRequest
        AuthnRequestImpl authReq = (AuthnRequestImpl) samlReq;
        AuthnRequestValidator.validate(authReq);

        String useMandate = request.getParameter(PARAM_USEMANDATE);
        if (useMandate != null) {
            if (useMandate.equals("true") && attributeConsumer != null) {
                if (!CheckMandateAttributes.canHandleMandate(attributeConsumer)) {
                    throw new MandateAttributesNotHandleAbleException();
                }
            }
        }

        String oaURL = moaRequest.getEntityMetadata().getEntityID();
        oaURL = StringEscapeUtils.escapeHtml(oaURL);

        Logger.info("Dispatch PVP2 AuthnRequest: OAURL=" + oaURL + " Binding=" + consumerService.getBinding());

        PVPTargetConfiguration config = new PVPTargetConfiguration();
        config.setOAURL(oaURL);
        config.setBinding(consumerService.getBinding());
        config.setRequest(moaRequest);
        config.setConsumerURL(consumerService.getLocation());

        //parse AuthRequest
        config.setPassiv(authReq.isPassive());
        config.setForce(authReq.isForceAuthn());

        return config;
    }

    /**
     * PreProcess AuthResponse and Assertion 
     * @param msg
     */
    private MOAResponse preProcessAuthResponse(MOAResponse msg) {
        Logger.debug("Start PVP21 assertion processing... ");
        Response samlResp = (Response) msg.getResponse();

        try {
            if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {

                //validate PVP 2.1 assertion
                SAMLVerificationEngine.validateAssertion(samlResp, true);

                msg.setSAMLMessage(SAML2Utils.asDOMDocument(samlResp).getDocumentElement());
                return msg;

            } else {
                Logger.debug("Receive StatusCode " + samlResp.getStatus().getStatusCode().getValue()
                        + " from interfederated IDP.");

            }

        } catch (IOException e) {
            Logger.warn("Interfederation response marshaling FAILED.", e);

        } catch (MarshallingException e) {
            Logger.warn("Interfederation response marshaling FAILED.", e);

        } catch (TransformerException e) {
            Logger.warn("Interfederation response marshaling FAILED.", e);

        } catch (AssertionValidationExeption e) {
            //error is already logged, to nothing
        }

        return null;
    }
}